漫画理解了TCP连接的实现以后,客户端的并发也爆发了
2022-10-02 16:37:24 来源:IT之家 阅读量:8956
echo " 500065000 "/proc/sys/net/IP v4/IP本地端口范围
连接:192 . 168 . 1 . 101 5000 192 . 168 . 1 . 100 8090
连接:192 . 168 . 1 . 101 5001 192 . 168 . 1 . 100 8090
连接:192.168.1.101...192.168.1.100 8090
连接6W:192 . 168 . 1 . 101 65000 192 . 168 . 1 . 100 8090
//将整个系统可以打开的文件描述符修改为20 we CHO 200000 gt,/proc/sys/fs/file—max//修改所有用户每个进程可以打开的文件的描述符是20w # VI/etc/sysctl . conf fs . NR _ open = 210000 # sysctl—p # VI/etc/security/limits . conf * soft nofile 200000 * hard nofile 20000
注意:limits中的硬限制不能超过nr_open,所以应该先更改nr_open而且最好是在sysctl.conf中更改,硬限制在重启时生效,而nr_open不生效,导致启动问题
socket中有一个主要的数据结构sock_common,里面有两个联合体。
//file:include/net/sock . hstructsock _ common union _ _ addrpairskc _ addr pair,//TCP连接IP对struct _ _ be32skc _ daddr_ _ be32skc _ rcv _ saddr,,union _ _ portpairskc _ portpair//TCP连接端口对struct _ _ be16skc _ dport_ _ u16skc _ num,,
其中,skc_addrpair记录TCP连接中的IP对,skc_portpair记录端口对
网络包到达网卡后,依次经过DMA,硬中断,软中断等过程,最后发送到socket的接收队列。
对于TCP协议,协议处理的入口函数是tcp_v4_rcv我们来看看它的代码
//file:net/IP v4/TCP _ IP v4 . cinttcp _ v4 _ rcv th = TCP _ HDR,//Get tcpheaderiph = IP _ HDR,//获取IP头k = _ _ inet _ lookup _ skb,
//file:include/net/inet _ hashtables . hstaticinlinestructsock * _ _ inet _ lookup 16 hnum = ntohs,struct sock * sk = _ _ inet _ lookup _ established,returnsk。:__inet_lookup_listener,
首先确定是否有处于连接状态的套接字,这将转到__inet_lookup_established函数
strut Sock * _ _ inet _ lookup _ established//将源端口和目的端口拼成32位int integer const _ _ portpairports = inet _ combined _ ports,//内核使用hash方法加快套接字搜索。unsignedinash = inet _ ehashfn,unsignedintslot = hashamphashinfo—gt,ehash _ maskstruct inet _ ehash _ bucket * head = amp,hashinfo—gt,ehash,Begin://遍历链表,逐个比较,直到找到sk _ nulls _ for _ each _ rcu if继续,if))if(likely(!原子_ Inc _ not _ zero(amp,sk—gt,sk _ ref CNT)))gotobegintw,如果(不太可能(!INET_MATCH(sk,NET,acookie,saddr,daddr,ports,dif)))sock _ put(sk),gotobegingotoout
//include/net/inet _ hashtables . h # define net _ MATCH ((inet _ sk(_ _ sk)—inet _ port pair(_ _ ports))amp,amp (inet _ sk(_ _ sk)—inet _ daddr(_ _ saddr))amp,amp (inet _ sk(_ _ sk)—inet _ rcv _ saddr(_ _ daddr))amp,amp(!(_ _ sk)—sk _ bound _ dev _ if ((_ _ sk)—sk _ bound _ dev _ if(_ _ dif)))amp,ampnet_eq(sock_net(__sk),(__net)))
将网络数据包的tcp报头中的__saddr,__daddr,__ports与INET_MATCH中Linux的socket中的inet_portpair,inet_daddr,inet_rcv_saddr进行比较如果与插座匹配,就会被找到当然除了ip和端口,INET_MATCH还比较一些其他的东西,所以TCP有五元组,七元组等等
WC—l 1000013 # cat/proc/meminfoMemTotal:3925408 kbmemfree:97748 kbbuffers:35412 kbcached:119600 kbs lab:3241528 kb
摘要
客户端每建立一个连接就消耗一个端口,所以很多同学看到客户端机器上的连接数超过3W或者5W就紧张,总觉得机器要出问题了。
这篇文章第一版是很久以前写的,但是飞哥打磨了很久才满意本文展示了TCP socket的部分内核代码
TCP连接是客户机和服务器上的一对套接字都是在各自的内核对象上记录双方的ip对和端口对,通过这个找到对方
当TCP发送方发送网络数据包时,它会将此信息复制到IP报头中网络通过互联网获取该令牌并到达目的服务器目标服务器内核将匹配IP数据包报头中携带的令牌,以找到正确的套接字
在这个过程中,我们可以看到,客户端的端口在这个四联中只有一元。即使两个连接使用同一个端口号,只要客户端ip不同或者服务器不同,也不会影响内核正确找到对应的连接,不会出现交叉连接!
因此,有两种方法可以提高客户端中TCP的最大并发性第一种方法是为客户端配置多个IP第二种方法是连接多个不同服务器
但是,最好不要将两种方法混用因为使用多个IP时,客户端需要绑定一旦绑定,内核在建立连接时不会选择使用的端口
最后,我们自己的实验证明,客户端也可以突破百万并发订单相信看过这篇文章的你,再也不会害怕65535这个数字了
声明:本网转发此文章,旨在为读者提供更多信息资讯,所涉内容不构成投资、消费建议。文章事实如有疑问,请与有关方核实,文章观点非本网观点,仅供读者参考。
猜您喜欢