说在前面
- 环境: WSL
- 参考: UNIX网络编程、linux manual page
数据类型说明
数据类型 | 说明 | 头文件 |
socklen_t | 套接字地址结构的长度,一般为uint32_t | <sys/socket.h> |
struct sockaddr | 见套接字地址结构 | <sys/socket.h> |
基本说明
accept函数由服务端调用,用于已完成连接队列队首(见listen函数)返回下一个已完成连接。在阻塞前提下,若已完成连接队列为空,进程将投入睡眠。
-
定义
#include <sys/socket.h> int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);
参数说明:
- sockfd
套接字描述符。
在讨论accept函数时,该套接字描述符又被称为监听套接字描述符(在服务器上由socket创建,并作为bind和listen的第一个参数);而accept的返回值被称为已连接套接字描述符。
一个服务器(进程)通常仅仅创建一个监听套接字,它在该服务器(进程)的生命周期中一直存在。
内核为每个由服务器进程接受的连接(已完成三路握手)创建一个已连接套接字。当服务器完成对某个客户的服务后,就可以关闭相应的已连接套接字。 - cliaddr
作为返回值,返回对端进程(客户)的协议地址。若对客户身份不感兴趣,该参数可与第三个参数同时置为空指针。 - addrlen
值-结果参数。作为值,该指针指向由cliaddr所指的套接字地址结构的长度;作为结果,指向内核实际存放在该地址结构中的字节数。该参数可与第二个参数同时置为空指针。
返回值:
- 若成功,则返回一个由内核生成的全新描述符,代表与客户的连接;若失败,返回-1。
- sockfd
栗子
- 代码:github
inet_ntop函数、ntohs函数len = sizeof(cliaddr); if( (connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &len)) < 0) { /* ... */ } printf("connection from %s, port %d\n", inet_ntop(AF_INET, &cliaddr.sin_addr, buff, sizeof(buff)), ntohs(cliaddr.sin_port));
- 环境:同一台主机运行一个服务端以及两个客户端
在本例中,client程序未调用bind函数,将由内核选择源IP地址(见bind函数)。在./client.out 127.0.0.1时,内核将源IP设置为环回地址;在./client.out 192.168.3.9时,内核将源IP设置为以太网接口IP。