1
回答
TCP串行服务器阻塞在read时,第二个连接能完成三路握手协议。
滴滴云服务器,限时包月0.9元,为开发者而生>>>   
#include<stdio.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<errno.h>
#include<signal.h>
#include<sys/wait.h>
#include<sys/select.h>
#include<sys/time.h>


void handler(int signal)
{
pid_t pid;
int stat;
while((pid = waitpid(-1, &stat, WNOHANG)) > 0)
printf("child %d terminated\n",pid);
return;
}
int server(int fd)
{
char buff[16] = {0};
int n;
while(1){
again:
printf("begain\n");
if((n = read(fd, buff, sizeof(buff))) > 0){//连接成功后阻塞在此处。
printf("buff=%s\n",buff);
write(fd, buff, n);
}
else if(n < 0 && errno == EINTR){
goto again;
}
else if(n < 0){
fprintf(stderr, "read error.\n");
close(fd);
exit(-1);
}
else if(n == 0){
return 0;
}
}
}


int main()
{
pid_t pid;
int sockfd;
int connfd;
int maxfd;
int ret;
struct sockaddr_in address;
struct sockaddr_in cliaddr;
int cliaddlen;
struct timeval timeout;
fd_set rd_set;

sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0){
fprintf(stderr,"creat socket error.\n");
return -1;
}
bzero(&address, sizeof(struct sockaddr_in));
address.sin_family = AF_INET;
address.sin_port = htons(1234);
address.sin_addr.s_addr = htonl(INADDR_ANY);
ret = bind(sockfd, (struct sockaddr *)&address, sizeof(address));
printf("ret=%d\n",ret);
printf("bind success\n");
ret = listen(sockfd, 14);
//signal(SIGCHLD, handler);
printf("ret=%d\n",ret);
printf("listen success\n");
cliaddlen = sizeof(cliaddr);
FD_ZERO(&rd_set);
FD_SET(sockfd, &rd_set);
maxfd = sockfd;
while(1){
printf("cd while\n");
//if(select(maxfd+1, &rd_set, NULL, NULL, NULL) > 0){
connfd = accept(sockfd, (struct sockaddr *)&cliaddr, &cliaddlen);
if(connfd < 0){
if(errno == EINTR)
continue;
else{
fprintf(stderr,"accept error.\n");
close(sockfd);
return -1;
}
}
//}
printf("connfd success\n");
server(connfd);
}

}

服务器代码如上,我用一个客户连这个服务器后,再用另外一个客户去连接。按理说第一个客户去连,完成三路握手后阻塞在read函数处,可用第二个客户去连的的时候三路握手协议还能完成,这是为什么?

<无标签>
举报
我爱c语言
发帖于2年前 1回/174阅
共有1个答案 最后回答: 2年前

TCP 协议栈内部,会根据 int listen(int sockfd, int backlog); 中的 backlog 的值做相应的处理,以下内容来自 man listen:

The  backlog  argument defines the maximum length to which the queue of pending connections for sockfd may grow.  If a connection request arrives when the queue is full, the client may receive an error with
       an indication of ECONNREFUSED or, if the underlying protocol supports retransmission, the request may be ignored so that a later reattempt at connection succeeds.
...

The  behavior of the backlog argument on TCP sockets changed with Linux 2.2.  Now it specifies the queue length for completely established sockets waiting to be accepted, instead of the number of incomplete
       connection requests.  The maximum length of the queue for incomplete sockets can be set using /proc/sys/net/ipv4/tcp_max_syn_backlog.  When syncookies are enabled there is no logical maximum length and this
       setting is ignored.  See tcp(7) for more information.


       If  the  backlog argument is greater than the value in /proc/sys/net/core/somaxconn, then it is silently truncated to that value; the default value in this file is 128.  In kernels before 2.4.25, this limit
       was a hard coded value, SOMAXCONN, with the value 128.

也就是说,在 TCP 协议栈内部维护 completely established sockets 的 queue 未达到最大值之前,新的客户端连接时会被 TCP 协议栈所接受的。至于是否阻塞在 read 上,这个对底层的行为不产生影响。

--- 共有 1 条评论 ---
我爱c语言谢谢 2年前 回复
顶部