SOCKET编程之一个端口如何建立多个TCP连接?(用fork子进程selectpollepoll都是可以的)一个端口最大支持建立多少个tcp连接?

Posted Dontla

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SOCKET编程之一个端口如何建立多个TCP连接?(用fork子进程selectpollepoll都是可以的)一个端口最大支持建立多少个tcp连接?相关的知识,希望对你有一定的参考价值。

文章目录

文章1:不太清楚socket一个端口如何建立多个tcp连接,这边转载一篇文章

一、背景

记得上学期暑假的时候我基于MFC写了一个简单的聊天程序。那个聊天程序,两部分组成,监听客户端请求线程和客户端请求处理线程。

1.服务器接收到登陆请求,验证登陆信息后,如果通过验证建立新线程与其交互,并通知用户连接到新的端口,并创建好新端口的SOCKET连接。

2.然后将用户类和新端口传给新建立的客户端请求处理线程。

当时,可能是没理解好的原因,误以为,一个端口同一时间只能建立起一个TCP连接。所以写这个聊天程序时才会每一个用户分配一个新的端口。

之前,自己了解HTTP后,接触到web应用开发的时候,就疑惑了,web server接收浏览器的请求,都是从80端口接受请求。当时没仔细去想,就以为web server和我那个聊天程序一样,会去建立新的线程与其进行请求处理。

二、问题

最近,写爬虫的时候用到了Smsniff去抓包。发现,一个http请求中。往往是只与服务器的80端口进行通信。这就与我记忆中的SOCKET冲突了。于是今天写了个小代码测试了一下,一个端口,真的能建立多个连接。

三、代码逻辑流程

1.server

①服务端主线程:负责监听5174端口,如果有请求,accept到系统分配的SOCKET(为unsigned int, recv接受函数就需要这个SOCKET)于是建立一个新线程,将这个SOCKET通过lpParament传递给新线程。

②服务器信息接受线程:负责从lpParment从拿到SOCKET并,recv客户端发来的信息。

2.client

连接到服务器的5174端口,并发送消息。

四、执行结果

一个端口的确能同时建立多条TCP请求。

五、理解

综合部分网上看到的资料。我的理解是,一个连接的唯一标识是[server ip, server port, client ip, client port]也就是说。操作系统,接收到一个端口发来的数据时,会在该端口,产生的连接中,查找到符合这个唯一标识的并传递信息到对应缓冲区。

1.一个端口同一时间只能bind给一个SOCKET。就是同一时间一个端口只可能有一个监听线程(监听listen之前要bind)。

2.为什么一个端口能建立多个TCP连接,同一个端口也就是说 server ip和server port 是不变的。那么只要[client ip 和 client port]不相同就可以了。能保证接唯一标识[server ip, server port, client ip, client port]的唯一性。

六、疑问解答

1.如果监听的线程释放掉监听用的SOCKET了,会影响之前通过这个监听SOCKET建立的TCP连接么?

答案:并不会,SOCKET之间是独立的,不会有影响(我已经自己写了程序验证了,读者可以自己写代码验证)。

2.一个端口能建立多个UDP连接么?

答案:UPD本身就是无连接的。所以不存在什么多个UDP连接。只是,服务端接收UDP数据需要bind一个端口。一个SOCKET只能绑定到一个端口。

参考文章:SOCKET编程之一个端口能建立多个TCP连接?

文章2:一台Linux服务器最多能支撑多少个TCP连接?

1、一次关于服务器端并发的聊天

TCP连接四元组是源IP地址、源端口、目的IP地址和目的端口。任意一个元素发生了改变,那么就代表的是一条完全不同的连接了。拿我的nginx举例,它的端口是固定使用80。另外我的IP也是固定的,这样目的IP地址、目的端口都是固定的。剩下源IP地址、源端口是可变的。所以理论上我的Nginx上最多可以建立2的32次方(ip数)×2的16次方(port数)个连接。这是两百多万亿的一个大数字!!

进程每打开一个文件(linux下一切皆文件,包括socket),都会消耗一定的内存资源。如果有不怀好心的人启动一个进程来无限的创建和打开新的文件,会让服务器崩溃。所以linux系统出于安全角度的考虑,在多个位置都限制了可打开的文件描述符的数量,包括系统级、用户级、进程级。这三个限制的含义和修改方式如下:

  • 系统级:当前系统可打开的最大数量,通过fs.file-max参数可修改
  • 用户级:指定用户可打开的最大数量,修改/etc/security/limits.conf
  • 进程级:单个进程可打开的最大数量,通过fs.nr_open参数可修改

我的接收缓存区大小是可以配置的,通过sysctl命令就可以查看。

$ sysctl -a | grep rmem
net.ipv4.tcp_rmem = 4096 87380 8388608
net.core.rmem_default = 212992
net.core.rmem_max = 8388608

其中在tcp_rmem"中的第一个值是为你们的TCP连接所需分配的最少字节数。该值默认是4K,最大的话8MB之多。也就是说你们有数据发送的时候我需要至少为对应的socket再分配4K内存,甚至可能更大。

TCP分配发送缓存区的大小受参数net.ipv4.tcp_wmem配置影响。

$ sysctl -a | grep wmem
net.ipv4.tcp_wmem = 4096 65536 8388608
net.core.wmem_default = 212992
net.core.wmem_max = 8388608

在net.ipv4.tcp_wmem"中的第一个值是发送缓存区的最小值,默认也是4K。当然了如果数据很大的话,该缓存区实际分配的也会比默认值大。


2、服务端百万连接达成记’

准备啥呢,还记得前面说过Linux对最大文件对象数量有限制,所以要想完成这个实验,得在用户级、系统级、进程级等位置把这个上限加大。我们实验目的是100W,这里都设置成110W,这个很重要!因为得保证做实验的时候其它基础命令例如ps,vi等是可用的。


活动连接数量确实达到了100W:

$ ss -n | grep ESTAB | wc -l  
1000024

当前机器内存总共是3.9GB,其中内核Slab占用了3.2GB之多。MemFree和Buffers加起来也只剩下100多MB了:

$ cat /proc/meminfo
MemTotal:        3922956 kB
MemFree:           96652 kB
MemAvailable:       6448 kB
Buffers:           44396 kB
......
Slab:          3241244KB kB

通过slabtop命令可以查看到densty、flip、sock_inode_cache、TCP四个内核对象都分别有100W个:

结论:socket服务端只用开一个端口监听(listen)socket请求就行,理论上来说,最大能支持2的32次方(ip数)×2的16次方(port数)个连接,但是linux对打开文件数有限制(65536个,每个socket连接占用一个文件),如果想支持更多,需要修改系统级/用户级/进程级

参考文章:一个服务端端口能建立多个TCP连接吗

文章3:为什么服务端需要产生两个socket(listen_socket_fd和connect_socket_fd)

为什么服务端需要产生两个socket(listen_socket_fd和connect_socket_fd)
答:监听socket是服务器作为客户端连接请求的一个对端,只需创建一次即可,它存在于服务器的整个生命周期,可为成千上万的客户端服务,而一旦一个客户端和服务器连接成功,完成了TCP三次握手,操作系统内核就为这个客户端生成一个已连接套接字(connect_socket_fd),让应用服务器使用这个connect_socket_fd和客户端进行通信,如果应用服务器完成了对这个客户端的服务,那么关闭的就是已连接套接字,这样就完成了TCP连接的释放。请注意,这个时候释放的只是这一个客户端连接,其它被服务的客户端连接可能还存在。最重要的是,监听套接字一直都处于“监听”状态,等待新的客户请求到达并服务。若只使用一个listen_socket_fd完成从创建监听到被请求连接,处理请求,关闭socket的整个过程,那么这个socket就会一直被占用,而不能被其它的客户端请求,造成服务端性能低下。使用两个socket,按职责分工,listen_socket_fd专门负责响应客户端的请求,每个新的connect_socket_fd专门负责该次连接的数据交互,分层协作,提高服务端的性能。

先放着,去看其他的先。。。

20220512 一个端口当然是可以建立多个tcp连接的,以socket服务端为例,bind一个端口后监听,可以用fork子线程的方法去处理socket_fd;如果不想用子线程处理,也可以用select,或者poll或者epoll,都是可以的

参考文章:linux C/C++多进程教程(多进程原理以及多进程的应用【以多连接socket服务端为例(fork子进程处理socket_fd),同时介绍了僵尸进程产生原因与解决方法】)(getpid、fork)

20220512 像上面说维持了100W条长连接,应该绝对没有fork子进程,否则子进程怎么够呢?估计是单线程,用select或poll、epoll方法,一个连接占用一个文件描述符(上文图中称为“文件句柄”)

以上是关于SOCKET编程之一个端口如何建立多个TCP连接?(用fork子进程selectpollepoll都是可以的)一个端口最大支持建立多少个tcp连接?的主要内容,如果未能解决你的问题,请参考以下文章

python网络编程之TCP编程

JAVA网络编程TCP通信

python基础之socket编程(TCP三次握手和四次挥手)

老雷socket编程之认识常用协议

TCP server 为什么一个端口可以建立多个连接?

TCP socket调试工具怎么建虚拟接收端