服务端不调用accept,客户端connect能否成功?

   文章来源:https://blog.csdn.net/zhangjiehuan/article/details/93364890 

   如题,服务端调用listen处于监听状态,假如其不调用accept函数,客户端的connect函数能否调用成功?

    我们做个试验试试:

 1//服务端server.c
 2#include <sys/types.h>
 3#include <sys/socket.h>
 4#include <stdio.h>
 5#include <netinet/in.h>
 6#include <arpa/inet.h>
 7#include <unistd.h>
 8#include <string.h>
 9#include <stdlib.h>
10#include <fcntl.h>
11#include <sys/shm.h>
12#include <assert.h>
13
14int main()
15{
16    int serverfd = socket( PF_INET, SOCK_STREAM, 0 );
17    assert( serverfd >= 0 );
18
19    struct sockaddr_in address;
20    bzero( &address, sizeof( address ) );
21    address.sin_family = AF_INET;
22    address.sin_addr.s_addr = htonl(INADDR_ANY);
23    address.sin_port = htons( 54321 );
24
25    int ret = bind( serverfd, ( struct sockaddr* )&address, sizeof( address ) );
26    assert( ret != -1 );
27
28    ret = listen( serverfd, 5 );
29    assert( ret != -1 );
30
31    printf("server listen on 54321\n");
32
33    while(1) 
34    {
35        sleep(5);
36    }
37    close(serverfd);
38
39    return 0;
40}

    上面是服务端代码,然后我在windows下使用telnet命令模拟客户端(telnet不仅可以实现远程登录,还可以探测服务端开放了哪些端口,不知道的童鞋,去问问度娘吧~)

1[root@promote ~]# gcc server.c -o server
2[root@promote ~]# ./server 
3server listen on 54321

  我们先使用netstat命令查看其状态,如下 

1[root@localhost ~]# netstat -at | grep 54321
2tcp        0      0 0.0.0.0:54321           0.0.0.0:*               LISTEN

然后我们使用telnet命令连接,看能否建立连接

 

 

我们再使用netstat查看服务端状态

1[root@localhost ~]# netstat -at | grep 54321
2tcp        1      0 0.0.0.0:54321           0.0.0.0:*               LISTEN     
3tcp        2      0 promote.cache-dns:54321 promote.cache-dns:60530 ESTABLISHED

    实验结果表明:服务端即使不调用accept,客户端依然可以connect成功。

    这是什么原因呢?我们先上张图,如下:

    当客户端调用connect函数时,将引发三次握手过程,如上图所示,客户端首先发送SYN请求分组,此时服务端会将请求放入SYN队列,同时向客户端发送ACK确认报文,然后客户端向服务端再次发送ACK报文。服务端收到ACK确认报文后,将SYN里的连接请求移入ACCEPT队列。此时三次握手结束,即TCP连接成功建立。然后内核通知用户空间的阻塞的服务进程,服务进程调用accept仅仅是从ACCEPT队列里取出一个连接而已。也就是说客户端调用connect连接服务器,与服务器调用accept“接受”连接是两个独立的过程。

    上图中SYN队列和ACCEPT队列分别称为半连接队列与全连接队列。还记得listen函数怎么调用的吗?其原型如下:

1#include <sys/socket.h>
2
3int listen(int s, int backlog);

第二个参数backlog是什么意思?对,它就是全连接队列的长度。那么它有长度限制吗?当然有了,使用如下命令即可查看其最大值。

1[root@promote ~]# cat /proc/sys/net/core/somaxconn 
2128
3[root@promote ~]#

    也就是listen函数的第二个参数的最大不会超过128,即

1len = min (backlog,/proc/sys/net/core/somaxconn)

 

    上面刚才说了,还有个半连接队列,那它的最大值是多少呢?其实它的取值遵循如下规则:

1syn_len = min (backlog, /proc/sys/net/core/somaxconn, /proc/sys/net/ipv4/tcp_max_syn_backlog)

    好了,现在大家对题目提出的问题,应该清楚了吧,欢迎关注公众号,深入交流~

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值