
作业社区
探索学习新天地,共享知识资源!
浪潮君 的学生作业:
#include // 标准输入输出函数,如 printf、perror #include // 提供 exit() 等函数 #include // 字符串处理函数,如 memset、strcmp #include // 提供 close()、read()、write() 等函数 #include // 提供网络地址转换函数,如 inet_ntoa、htons // ----------------- 宏定义 ----------------- #define SERVER_PORT 8888 // 服务器监听的端口号 #define BUFFER_SIZE 1024 // 数据缓冲区大小 #define BACKLOG 5 // 监听队列的最大长度(排队等待 accept 的客户端数量) int main() { int listen_fd, conn_fd; // listen_fd:监听 socket;conn_fd:已连接 socket struct sockaddr_in server_addr, client_addr; // 存储服务器/客户端的 IP 和端口 socklen_t client_len; // 用于记录 client_addr 的长度 char buffer[BUFFER_SIZE]; // 数据缓冲区,用于接收与发送 // ---------- 1. 创建 TCP socket ---------- listen_fd = socket(AF_INET, SOCK_STREAM, 0); // 创建面向连接(TCP)的 IPv4 套接字 if (listen_fd < 0) { perror("socket 创建失败"); // 若创建失败,输出错误信息并退出 exit(1); } // ---------- 2. 配置服务器地址 ---------- memset(&server_addr, 0, sizeof(server_addr)); // 清空 server_addr 结构体 server_addr.sin_family = AF_INET; // 使用 IPv4 协议族 server_addr.sin_addr.s_addr = INADDR_ANY; // 监听本机所有网卡上的连接 server_addr.sin_port = htons(SERVER_PORT); // 设置监听端口(主机字节序 → 网络字节序) // ---------- 3. 绑定 socket ---------- if (bind(listen_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) { perror("bind 绑定失败"); // 绑定失败通常是端口被占用 close(listen_fd); // 关闭 socket exit(1); } // ---------- 4. 启动监听 ---------- if (listen(listen_fd, BACKLOG) < 0) { perror("listen 监听失败"); close(listen_fd); exit(1); } printf("服务器已启动,监听端口 %d...\n", SERVER_PORT); // ---------- 5. 主循环:接受客户端连接 ---------- while (1) { client_len = sizeof(client_addr); // 设置 client_len 的初始值(必须) // 等待客户端连接(阻塞),返回用于通信的新 socket conn_fd = accept(listen_fd, (struct sockaddr*)&client_addr, &client_len); if (conn_fd < 0) { perror("accept 失败"); // accept 失败也不会退出服务,继续等待下一个连接 continue; } // 打印客户端的 IP 和端口(便于调试) printf("客户端已连接:%s:%d\n", inet_ntoa(client_addr.sin_addr), // 将 IP 转为字符串 ntohs(client_addr.sin_port)); // 将端口从网络字节序转为主机字节序 // ---------- 6. 收发消息循环 ---------- while (1) { // 接收客户端发来的数据 ssize_t len = recv(conn_fd, buffer, sizeof(buffer) - 1, 0); if (len