accept
函数用于从监听队列中取出一个已完成的连接请求,并创建一个新的套接字来处理这个连接。这是服务器端网络编程中的一个关键步骤。函数原型如下:
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
参数说明
-
sockfd
:监听的套接字描述符,通常是由socket
函数创建并经过bind
和listen
函数设置的。 -
addr
:指向一个struct sockaddr
类型的指针,用于存储客户端的地址信息。如果不需要获取客户端地址,可以传入NULL
。 -
addrlen
:指向一个socklen_t
类型的指针,用于指定addr
参数所指向的缓冲区的长度。如果addr
为NULL
,则addrlen
也应为NULL
。
返回值
-
成功时返回一个新的套接字描述符,用于与客户端进行通信。
-
失败时返回
-1
,并设置errno
错误码。
使用场景
accept
函数通常在服务器端使用,用于从监听队列中取出客户端的连接请求,并创建一个新的套接字来处理这个连接。原监听套接字继续监听新的连接请求。
示例代码
以下是一个简单的服务器端代码示例,展示了如何使用accept
函数:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main() {
int sockfd, new_sockfd, ret;
struct sockaddr_in serv_addr, cli_addr;
socklen_t cli_len = sizeof(cli_addr);
// 创建套接字
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
// 配置服务器地址结构
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY; // 绑定到所有可用的网络接口
serv_addr.sin_port = htons(8080); // 绑定到端口8080
// 绑定套接字到指定地址和端口
if (bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1) {
perror("bind failed");
close(sockfd);
exit(EXIT_FAILURE);
}
// 开始监听传入的连接请求
if (listen(sockfd, 5) == -1) { // 设置最大连接队列为5
perror("listen failed");
close(sockfd);
exit(EXIT_FAILURE);
}
printf("Server is listening on port 8080...\n");
while (1) {
// 接受客户端连接
new_sockfd = accept(sockfd, (struct sockaddr*)&cli_addr, &cli_len);
if (new_sockfd == -1) {
perror("accept failed");
continue;
}
// 获取客户端地址信息
char client_ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &cli_addr.sin_addr, client_ip, INET_ADDRSTRLEN);
printf("Accepted connection from %s:%d\n", client_ip, ntohs(cli_addr.sin_port));
// 处理客户端连接...
close(new_sockfd);
}
close(sockfd);
return 0;
}
说明
-
套接字创建:使用
socket
函数创建一个TCP套接字。 -
绑定地址:使用
bind
函数将套接字绑定到服务器的IP地址和端口号。 -
监听连接:使用
listen
函数将套接字设置为监听模式,等待客户端连接。 -
接受连接:使用
accept
函数从监听队列中取出一个已完成的连接请求,并创建一个新的套接字来处理这个连接。 -
处理客户端连接:使用新的套接字与客户端进行通信,处理完后关闭该套接字。
注意事项
-
accept
函数会阻塞,直到有客户端连接请求到达。 -
每次调用
accept
函数都会返回一个新的套接字描述符,原监听套接字继续监听新的连接请求。 -
如果需要同时处理多个客户端连接,可以考虑使用多线程或多进程的方式。
-
如果不需要获取客户端地址信息,可以将
addr
和addrlen
参数设置为NULL
。