为了账号安全,请及时绑定邮箱和手机立即绑定

作业社区

探索学习新天地,共享知识资源!

0 提交作业
0 布置作业
0 满分作业
得分 100
学习任务

浪潮君 的学生作业:

#include // 标准输入输出库 #include // 提供 exit(), malloc(), free() #include // 提供字符串操作函数,如 strlen(), strncpy(), memcpy() #include // 提供 close(), pthread_exit() #include // POSIX 线程库,用于创建和管理线程 #include // 提供 socket 通信接口 #include // 提供 sockaddr_in 结构和端口、地址常量 #include // 提供 inet_ntoa 等 IP 地址转换函数 #define SERVER_PORT 8888 // 服务器监听的 UDP 端口号 #define BUFFER_SIZE 1024 // 缓冲区大小(接收/发送用) #define PREFIX "回显: " // 回复前缀,回显消息统一加上该前缀 // 线程参数结构体:用于传递每条消息的上下文给线程处理 typedef struct { int sockfd; // socket 文件描述符 struct sockaddr_in client_addr; // 客户端地址结构体 char message[BUFFER_SIZE]; // 客户端发送的消息内容 ssize_t msg_len; // 客户端消息实际长度(字节数) } thread_arg_t; // 线程处理函数:每次接收到客户端数据后就创建线程执行该函数 void *handle_client(void *arg) { thread_arg_t *client = (thread_arg_t *) arg; // 将 void* 参数转换为 thread_arg_t* char reply[BUFFER_SIZE]; // 构造回复消息的缓冲区 size_t prefix_len = strlen(PREFIX); // 获取前缀长度 ssize_t reply_len = client->msg_len; // 获取客户端消息长度 // 防止拼接后超出 reply 缓冲区,进行长度截断处理 if (prefix_len + reply_len + 1 > BUFFER_SIZE) { reply_len = BUFFER_SIZE - prefix_len - 1; } // 拼接回显消息:将 "回显: " 前缀和客户端消息合并 memcpy(reply, PREFIX, prefix_len); // 复制前缀 memcpy(reply + prefix_len, client->message, reply_len); // 复制消息内容 reply[prefix_len + reply_len] = '\0'; // 添加字符串结束符 // 打印客户端的 IP、端口和消息内容 printf("收到来自 %s:%d 的数据 :%s\n", inet_ntoa(client->client_addr.sin_addr), // 将 IP 地址转为字符串 ntohs(client->client_addr.sin_port), // 将端口号从网络字节序转为主机字节序 client->message); // 打印原始消息 // 发送回显消息给客户端 sendto(client->sockfd, reply, prefix_len + reply_len, 0, (struct sockaddr*) &client->client_addr, sizeof(client->client_addr)); free(client); // 释放线程使用的动态内存 pthread_exit(NULL); // 线程退出 } // 主函数:负责 socket 初始化、接收数据并启动线程 int main(int argc, char *argv[]) { int sockfd; // socket 描述符 struct sockaddr_in server_addr, client_addr; // 服务器和客户端地址结构 socklen_t addr_len = sizeof(client_addr); // 客户端地址长度 // 创建 UDP socket,指定为 IPv4 + 无连接数据报类型 if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("sock failed"); // 打印错误信息 exit(EXIT_FAILURE); // 创建失败则退出 } // 初始化服务器地址结构体,清零后设置协议族、IP 和端口 memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; // 设置地址族为 IPv4 server_addr.sin_addr.s_addr = INADDR_ANY; // 接收任意本地地址的数据 server_addr.sin_port = htons(SERVER_PORT); // 绑定端口(主机字节序转网络字节序) // 将 socket 绑定到本地地址和端口 if (bind(sockfd, (struct sockaddr*) &server_addr, sizeof(server_addr)) < 0) { perror("bind failed"); // 打印绑定失败信息 close(sockfd); // 关闭 socket exit(EXIT_FAILURE); // 退出程序 } printf("多线程UDP服务器启动成功,监听端口 %d...\n", SERVER_PORT); // 主循环:持续接收客户端 UDP 消息,并为每条消息创建一个线程处理 while (1) { char buffer[BUFFER_SIZE]; // 接收缓冲区 // 接收客户端发送的 UDP 数据报 ssize_t recv_len = recvfrom(sockfd, buffer, BUFFER_SIZE - 1, 0, (struct sockaddr*) &client_addr, &addr_len); if (recv_len < 0) { perror("recvfrom failed"); // 接收失败,打印错误信息 continue; // 继续接收下一个客户端消息 } buffer[recv_len] = '\0'; // 添加字符串结束符,确保可打印 // 动态分配线程参数结构体 thread_arg_t *client = malloc(sizeof(thread_arg_t)); if (!client) { fprintf(stderr, "内存分配失败"); // 打印分配失败信息 continue; // 不处理当前消息,继续等待下一条 } // 填充线程参数结构体 client->sockfd = sockfd; // socket 描述符 client->client_addr = client_addr; // 客户端地址 client->msg_len = recv_len; // 消息长度 strncpy(client->message, buffer, BUFFER_SIZE); // 拷贝消息内容 client->message[BUFFER_SIZE - 1] = '\0'; // 手动添加结束符,避免溢出 // 创建线程处理当前客户端请求 pthread_t tid; if (pthread_create(&tid, NULL, handle_client, client) != 0) { perror("线程创建失败"); free(client); // 创建失败需释放内存 } // 设置线程为分离状态,自动释放资源(不需要 pthread_join) pthread_detach(tid); } close(sockfd); // 程序退出前关闭 socket return 0; }

得分 100
学习任务

浪潮君 的学生作业:

#include // 标准输入输出库 #include // 提供 exit() 函数 #include // 提供字符串处理函数,如 memset、strlen、memcpy #include // 提供 close() 等 POSIX API #include // 提供 socket 套接字函数 #include // 提供 sockaddr_in 结构 #include // 提供 inet_ntoa 等网络地址转换函数 #define SERVER_PORT 8888 // 服务器监听的 UDP 端口 #define BUFFER_SIZE 1024 // 通信缓冲区大小 #define PREFIX "回显:" // 回复消息前缀,用于构造回显内容 int main() { int sockfd; // socket 文件描述符 struct sockaddr_in server_addr; // 服务器地址结构体 struct sockaddr_in client_addr; // 客户端地址结构体 char buffer[BUFFER_SIZE]; // 接收客户端数据的缓冲区 socklen_t addr_len = sizeof(client_addr); // 客户端地址结构长度,recvfrom 会修改该值 // 创建 UDP socket,使用 IPv4 和数据报类型 sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { perror("socket 创建失败"); exit(EXIT_FAILURE); } // 清空服务器地址结构体内容 memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; // 设置地址族为 IPv4 server_addr.sin_addr.s_addr = INADDR_ANY; // 接收所有网卡上的数据 server_addr.sin_port = htons(SERVER_PORT); // 设置监听端口(主机字节序转网络字节序) // 清空保留字段,确保结构体干净(对齐结构、兼容某些系统) memset(&(server_addr.sin_zero), 0, 8); // 将 socket 与本地地址绑定 if (bind(sockfd, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) { perror("bind 绑定失败"); close(sockfd); exit(EXIT_FAILURE); } // 打印服务器启动提示 printf("UDP服务器启动成功,监听端口 %d...\n", SERVER_PORT); // 无限循环,持续接收和响应客户端消息 while (1) { // 从客户端接收 UDP 数据报,最多接收 BUFFER_SIZE - 1 字节,预留给 \0 ssize_t recv_len = recvfrom(sockfd, buffer, BUFFER_SIZE - 1, 0, (struct sockaddr *) &client_addr, &addr_len); // 接收失败时输出错误信息,继续下一次循环 if (recv_len < 0) { perror("recvfrom 接收失败"); continue; } // 添加字符串结束符,确保 buffer 是合法的 C 字符串 buffer[recv_len] = '\0'; // 打印客户端地址和收到的消息内容 printf("收到来自 %s:%d 的数据:%s\n", inet_ntoa(client_addr.sin_addr), // 将 IP 地址转换为字符串 ntohs(client_addr.sin_port), // 将端口号从网络字节序转为主机字节序 buffer); // 构造回复消息 char reply[BUFFER_SIZE]; // 回显缓冲区 size_t prefix_len = strlen(PREFIX); // 获取前缀长度 // 若前缀 + 接收数据 + '\0' 总长度超过缓冲区上限,则截断 if (prefix_len + recv_len + 1 > BUFFER_SIZE) { fprintf(stderr, "回显消息过长,已被截断\n"); recv_len = BUFFER_SIZE - prefix_len - 1; // 调整接收长度以防止越界 buffer[recv_len] = '\0'; // 重新添加结束符 } // 复制前缀到回复缓冲区的起始位置 memcpy(reply, PREFIX, prefix_len); // 将客户端发来的消息内容追加到前缀后面,并复制结束符 '\0' memcpy(reply + prefix_len, buffer, recv_len + 1); // 向客户端发送回显消息(前缀 + 原始消息),总长度为 prefix_len + recv_len 字节 if (sendto(sockfd, reply, prefix_len + recv_len, 0, (struct sockaddr *) &client_addr, addr_len) < 0) { perror("sendto 发送失败"); } } close(sockfd); return 0; }

得分 100
学习任务

Yam8632482 的学生作业:

#include #include typedef struct { char name[20]; int id; int score; } s_t; void input_student(s_t *s) { for (int i = 0; i < 3; i++) { printf(“请输入第%d个学生的信息:\n”,i+1); printf(“请输入姓名:”); scanf("%s",s[i].name); printf(“请输入学号:”); scanf("%d",&s[i].id); printf(“请输入分数:”); scanf("%d",&s[i].score); } } void output_student(s_t *s) { for (int i = 0; i < 3; i++) { printf(“第%d个学生的信息:\n”,i+1); printf(“姓名:%s\n”,s[i].name); printf(“学号:%d\n”,s[i].id); printf(“分数:%d\n”,s[i].score); } } s_t maxscore_student(s_t *s) { int max_score = 0; int max_index = 0; for (int i = 0; i < 3; i++) { if (s[i].score > max_score) { max_score = s[i].score; max_index = i; } } s_t max_student; strcpy(max_student.name,s[max_index].name); max_student.id = s[max_index].id; max_student.score = s[max_index].score; return max_student; } int main() { s_t s[3]; //要求设计一个input_student()函数,参数自己设计,用户从键盘输入3个学生的信息存放s 中 input_student(s); //然后设计一个ouput_student()函数,参数自己设计,输出3个学生的信息存放s中 output_student(s); //最后设计⼀个maxscore_student()函数,参数自己设计,返回3个学生中,分数最高人的信息。 s_t max_student = maxscore_student(s); printf(“name\tscore\tid\n”); printf("%s\t%d\t%d", max_student.name, max_student.score, max_student.id); return 0; }

微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号