accept返回的fd是否继承listen fd的options

博客介绍了在UNIX系统上,一些TCP套接字选项如SO_DEBUG、SO_KEEPALIVE等会被accept的fd从listen fd继承。由于三次握手在内核TCP协议栈,部分行为来不及在应用层设置,所以需从listen fd继承,且不同版本和操作系统行为可能不同,需进一步测试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<<UNIX Netwok programming>> 7.4

The following socket options are inherited by a connected TCP socket from the listening socket: SO_DEBUG,SO_DONTROUTE,SO_KEEPALIVE,SO_LINGER,SO_OOBINLINE,SO_RCVBUF,SO_RCVLOWAT,SO_SNDBUF,SO_SNDLOWAT,TCP_MAXSEG,TCP_NODELAY.This is importnat with TCP because the connected socket is not returned to a server by accept until the three-way handshake is completed by the TCP layer.To ensure that one of these socket options is set for the connected socket when the three-way handshake completes, we must set that option for the listening socket.

在UNIX系统上,这些socket optionSO_DEBUG, SO_DONTROUTE, SO_KEEPALIVE, SO_LINGER,SO_OOBINLINE, SO_RCVBUF, SO_RCVLOWAT, SO_SNDBUF, SO_SNDLOWAT, TCP_MAXSEG, TCP_NODELAY会被accept的fd从listen fd继承,因为三次握手在内核TCP协议栈,此时有些行为还来不及在应用层设置,所以需要从listen fd继承。

不同版本,不同操作系统行为可能不同,需要进一步测试。

int main() { /** * server_socket The server listens to the socket * opt Socket option value * server_addr Server address information * max_ser_socket */ int server_socket = -1; int opt = 1; struct sockaddr_in server_addr; int max_ser_socket = -1; fd_set rdset, rdtmp; FD_ZERO(&rdset); /* Create a server socket */ server_socket = socket(AF_INET, SOCK_STREAM, 0); if (server_socket < 0) { perror("socket creation failed"); exit(EXIT_FAILURE); } /* Set SO_REUSEADDR options */ if (setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) { perror("setsockopt failed"); close(server_socket); exit(EXIT_FAILURE); } /* Bind addresses and ports */ memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_port = htons(PORT); if (0 > bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) ) { perror("bind failed"); close(server_socket); exit(EXIT_FAILURE); } /* Start listening */ if (0 > listen(server_socket, BACKLOG)) { perror("listen failed"); close(server_socket); exit(EXIT_FAILURE); } printf("Server running on port %d, serving files from %s\n", PORT, ROOT_DIR); printf("Open http://localhost in your browser\n"); max_ser_socket = server_socket; FD_SET(server_socket, &rdset); /* Main loop: Accept and process connections */ while (1) { /** * client_addr Stores the client's address information * client_addr_len Used to store the length of client_addr structure * client_socket Store the socket descriptor of the client * fd Traverse the file descriptor collection */ int fd = 0; struct sockaddr_in client_addr; socklen_t client_addr_len = sizeof(client_addr); int client_socket = -1; /* A copy of rdset (a collection of read file descriptors). */ rdtmp = rdset; /* Call select listens for file descriptors in the rdtmp collection */ select(max_ser_socket + 1, &rdtmp, NULL, NULL, NULL); /* Loop through each file descriptor from 0 to max_ser_socket */ for (; fd < max_ser_socket + 1; fd++) { /* There is a reading event */ if (FD_ISSET(fd, &rdtmp)) { /* New connections */ if (fd == server_socket) { /* Accept the connection */ client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &client_addr_len); if (0 > client_socket) { perror("accept failed!"); close(client_socket); continue; } /* Add the new client socket and update the max_ser_socket */ FD_SET(client_socket, &rdset); max_ser_socket = client_socket > max_ser_socket ? client_socket : max_ser_socket; } else { /* Connected clients */ handle_request(fd); close(fd); FD_CLR(fd, &rdset); } } } } close(server_socket); return 0; }总结以上代码实现了哪些功能,按顺序说
最新发布
08-15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值