1. 基本概念
accept 函数是一个系统调用,用于在服务器端接受客户端的连接。它会将客户端的信息填入一个指定的套接字结构体中,并返回一个新的套接字描述符,用于与客户端通信。但请注意,accept 函数只能在套接字类型为 SOCK_STREAM(流套接字)的网络套接字上使用,也就是说,它只适用于 TCP 协议。
2. 函数原型
```
#include #include int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); ``` 3. 函数参数 * sockfd:服务器端绑定的套接字描述符。 * addr:指向一个用于存放客户端信息的 sockaddr 结构体。 * addrlen:addr 结构体的长度。 4. 函数返回值 * 如果成功,返回一个新的套接字描述符,该描述符可以用于与客户端通信。 * 如果出错,返回 -1,并设置 errno 变量来指示错误原因。 5. 函数使用方法 最基本的使用方法如下: ``` // 创建服务器端套接字 int sockfd = socket(AF_INET, SOCK_STREAM, 0); // 绑定服务器端套接字 struct sockaddr_in servaddr; memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(PORT); bind(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)); // 监听服务器端套接字 listen(sockfd, 10); // 接受客户端连接 struct sockaddr_in cliaddr; socklen_t cliaddrlen = sizeof(cliaddr); int connfd; connfd = accept(sockfd, (struct sockaddr*)&cliaddr, &cliaddrlen); // 与客户端通信 char buffer[MAXLINE]; recv(connfd, buffer, MAXLINE, 0); send(connfd, buffer, strlen(buffer), 0); // 关闭连接和套接字 close(connfd); close(sockfd); ``` 首先创建了服务器端套接字 sockfd,并将其绑定到指定的 IP 地址和端口号上。然后调用 listen 函数,将 sockfd 设置为监听状态,等待客户端连接请求。 当客户端连接请求到达服务器端时,accept 函数会接受该连接,并返回一个新的套接字描述符 connfd。通过 connfd,我们就可以与客户端建立通信,并完成一系列数据传输的操作。最后,我们需要关闭连接和套接字,释放资源。 6. 函数案例说明 以下是一个简单的服务器端程序,它可以处理多个客户端的连接请求。当客户端连接成功后,服务器端会自动发送一条欢迎消息,并等待客户端发送数据。当客户端发送 exit 消息时,服务器端会关闭该客户端连接,并等待下一个客户端的连接请求。 ``` #include #include #include #include #include #include ain(int argc, char *argv[]) { // 创建服务器端套接字 int listenfd = socket(AF_INET, SOCK_STREAM, 0); if (listenfd == -1) { perror("socket"); exit(1); } // 绑定服务器端套接字 struct sockaddr_in servaddr; memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(PORT); if (bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1) { perror("bind"); exit(1); } // 监听服务器端套接字 if (listen(listenfd, 10) == -1) { perror("listen"); exit(1); } // 处理客户端连接请求 while (1) { struct sockaddr_in cliaddr; socklen_t cliaddrlen = sizeof(cliaddr); // 接受客户端连接 int connfd = accept(listenfd, (struct sockaddr*)&cliaddr, &cliaddrlen); if (connfd == -1) { perror("accept"); exit(1); } // 打印客户端连接信息 char cliip[INET_ADDRSTRLEN]; printf("client IP: %s, port: %d\n", inet_ntop(AF_INET, &cliaddr.sin_addr, cliip, INET_ADDRSTRLEN), ntohs(cliaddr.sin_port)); // 发送欢迎消息 char buffer[MAXLINE] = "Welcome to my server!\n"; int n = send(connfd, buffer, strlen(buffer), 0); if (n == -1) { perror("send"); exit(1); } // 处理客户端数据 while (1) { memset(buffer, 0, MAXLINE); n = recv(connfd, buffer, MAXLINE, 0); if (n == -1) { perror("recv"); exit(1); } else if (n == 0) { printf("client closed.\n"); break; } else { printf("recv: %s\n", buffer); if (strcmp(buffer, "exit\n") == 0) { break; } } } // 关闭连接和套接字 close(connfd); } // 关闭服务器端套接字 close(listenfd); return 0; } ``` 我们可以打开多个终端,分别在不同的窗口中运行客户端程序,模拟多个客户端的连接。这里我们只给出一个简单的客户端程序,注意指定的 IP 地址和端口号要和服务器端一致。 ``` #include #include #include #include #include #include ain(int argc, char *argv[]) { // 创建客户端套接字 int sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) { perror("socket"); exit(1); } // 连接服务器端套接字 struct sockaddr_in servaddr; memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = inet_addr(SERVER_IP); servaddr.sin_port = htons(PORT); if (connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1) { perror("connect"); exit(1); } // 与服务器通信 char buffer[MAXLINE]; int n = recv(sockfd, buffer, MAXLINE, 0); if (n == -1) { perror("recv"); exit(1); } else { printf("%s", buffer); } while (1) { memset(buffer, 0, MAXLINE); fgets(buffer, MAXLINE, stdin); n = send(sockfd, buffer, strlen(buffer), 0); if (n == -1) { perror("send"); exit(1); } else if (strcmp(buffer, "exit\n") == 0) { break; } } // 关闭客户端套接字 close(sockfd); return 0; } ``` 总的来说,accept 函数是网络编程中非常重要的一部分,它实现了服务器端对客户端的接受和处理,是实现网络通信的关键。 壹涵网络我们是一家专注于网站建设、企业营销、网站关键词排名、AI内容生成、新媒体营销和短视频营销等业务的公司。我们拥有一支优秀的团队,专门致力于为客户提供优质的服务。 我们致力于为客户提供一站式的互联网营销服务,帮助客户在激烈的市场竞争中获得更大的优势和发展机会!
发表评论 取消回复