使用流式套接字编写一字符界面的通信程序,客户端在与服务器连接成功后,从键盘依次输人若干同学的姓名、学号、性别和考试成绩并发送给服务器端,要求使用结构体调用一次send()函数将同一同学的所有数据项发送到服务器,当输人的姓名为“end”时结束程序;服务器端显示连接成功的客户端的IP地址,然后接收并显示客户端发来的每个同学的姓名、学号、性别、考试成绩,收到“end"后结束。
时间: 2024-03-14 11:43:58 浏览: 15
好的,这是一个比较复杂的程序,需要分别编写客户端和服务器端的代码。我会分步骤进行讲解,先看客户端的代码。
客户端代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#define BUF_SIZE 1024
#define END_MSG "end"
struct student {
char name[20];
char id[10];
char gender[5];
float score;
};
void error_handling(char *message);
int main(int argc, char *argv[]) {
int sock;
struct sockaddr_in serv_addr;
struct student stu;
char msg[BUF_SIZE];
int str_len, idx = 0, read_len = 0;
if(argc != 3) {
printf("Usage : %s <IP> <port>\n", argv[0]);
exit(1);
}
sock = socket(PF_INET, SOCK_STREAM, 0);
if(sock == -1)
error_handling("socket() error");
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr(argv[1]);
serv_addr.sin_port = htons(atoi(argv[2]));
if(connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1)
error_handling("connect() error!");
printf("Connected to server\n");
while(1) {
printf("Enter student name: ");
scanf("%s", stu.name);
if(strcmp(stu.name, END_MSG) == 0) {
write(sock, END_MSG, strlen(END_MSG));
break;
}
printf("Enter student id: ");
scanf("%s", stu.id);
printf("Enter student gender: ");
scanf("%s", stu.gender);
printf("Enter student score: ");
scanf("%f", &stu.score);
// 将结构体数据转换为字符串
sprintf(msg, "%s %s %s %.2f", stu.name, stu.id, stu.gender, stu.score);
// 发送数据到服务器端
write(sock, msg, strlen(msg));
}
close(sock);
return 0;
}
void error_handling(char *message) {
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
```
客户端代码的主要流程如下:
1. 创建套接字;
2. 连接服务器;
3. 循环读取用户输入的学生信息,并发送到服务器;
4. 如果输入的学生姓名为“end”,则发送结束消息并退出循环;
5. 关闭套接字。
在循环读取用户输入的学生信息时,使用了一个结构体来存储学生的姓名、学号、性别和考试成绩,然后将结构体数据转换为字符串,再发送到服务器端。这里要求使用结构体调用一次send()函数将同一个学生的所有数据项发送到服务器。
下面是服务器端的代码。
服务器端代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#define BUF_SIZE 1024
#define END_MSG "end"
struct student {
char name[20];
char id[10];
char gender[5];
float score;
};
void error_handling(char *message);
int main(int argc, char *argv[]) {
int serv_sock, clnt_sock;
struct sockaddr_in serv_addr, clnt_addr;
socklen_t clnt_addr_size;
char msg[BUF_SIZE];
int str_len, i;
if(argc != 2) {
printf("Usage : %s <port>\n", argv[0]);
exit(1);
}
serv_sock = socket(PF_INET, SOCK_STREAM, 0);
if(serv_sock == -1)
error_handling("socket() error");
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(atoi(argv[1]));
if(bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1)
error_handling("bind() error");
if(listen(serv_sock, 5) == -1)
error_handling("listen() error");
clnt_addr_size = sizeof(clnt_addr);
clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);
if(clnt_sock == -1)
error_handling("accept() error");
printf("Client IP address: %s\n", inet_ntoa(clnt_addr.sin_addr));
while(1) {
// 读取客户端发送的数据
str_len = read(clnt_sock, msg, BUF_SIZE);
if(str_len == -1)
error_handling("read() error");
msg[str_len] = '\0';
// 如果收到的消息为“end”,则退出循环
if(strcmp(msg, END_MSG) == 0)
break;
// 将字符串数据转换为结构体
struct student stu;
sscanf(msg, "%s %s %s %f", stu.name, stu.id, stu.gender, &stu.score);
// 输出学生信息
printf("Name: %s\n", stu.name);
printf("ID: %s\n", stu.id);
printf("Gender: %s\n", stu.gender);
printf("Score: %.2f\n", stu.score);
}
close(clnt_sock);
close(serv_sock);
return 0;
}
void error_handling(char *message) {
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
```
服务器端代码的主要流程如下:
1. 创建套接字;
2. 绑定套接字;
3. 进入监听状态;
4. 接受客户端连接请求;
5. 循环读取客户端发送的消息,并将消息转换为结构体输出;
6. 如果收到的消息为“end”,则退出循环;
7. 关闭套接字。
在循环读取客户端发送的数据时,首先使用read()函数读取数据,然后将数据转换为结构体,最后输出学生信息。
这就是使用流式套接字编写一字符界面的通信程序的完整代码,如果有问题可以随时问我哦。
相关推荐
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)