在linux下socket是用一个文件描述符来表示,对于linux来说从某个socket读数据和从某个文件读数据是一样的;linux下文件描述符的范围是1024,也就是每个用户进行所能使用的最大的文件描述符的数量不能超过此值,但是这个值可以进行修改,在服务器程序中,该值可以修改为10w、20w甚至更大的值。

      socket可以用一个五元组来标识:<源地址,源端口,目的地址,目的端口,使用的协议>
例如:地址为A的主机欲用tcp协议从端口3256向地址为B的主机的5432端口发送消息,那用一个socket来表示上述数据传输就是:
<A,3256,B,5432,tcp>
      对于socket来说,五元组中的任何一个元素发生变化都表示一个新的socket。这5个元素分为三类:地址、端口和协议。其中:
      地址:
      一般都是指ip地址,例如常用的IPV4的ip地址形式为:210.45.0.12;一个地址就标识了一台主机,如果在通信程序中知道了对方的地址,你就知道往哪台机子上发送了。但是现在还不知道发给那台机子上的哪个程序。
      端口:
      端口的数据类型是unsigned short,为16位,因此端口的使用范围为0~65535,其中0~1024之间的端口为特殊用途,用户可以使用的端口范围需在1024~65535之间,端口标识了一个服务或者是应用程序。
      因此知道了一个地址+端口,就知道了向哪台机子的哪个程序发送数据。但是,现在还不知道跟对方通信是采用哪种协议,就像两个人要说话,但是还不知道该用英文说还是中文说。
      协议:

      协议是指通信双方使用的通信协议,例如tcp、udp之类。协议就表明了双方采用什么方式进行通信。

      因此,知道:地址+端口+协议,就知道了向哪个机子的哪个程序使用哪个协议进行通信。


      为什么使用客户端测试服务器时,一台客户端主机的socket连接只能到6万多个,而服务器却可以接受10w、20万的连接(这里所说的连接就是socket)

例如:

使用一台服务器S和3个测试客户端C1、C2、C3进行测试,具体情况为:
服务器程序S运行的主机地址为:192.168.4.220,监听端口为1883。
测试客户端程序C1运行的主机地址为:192.168.4.221
测试客户端程序C2运行的主机地址为:192.168.4.222
测试客户端程序C3运行的主机地址为:192.168.4.223
此时在测试客户端程序C1、C2、C3中一直创建新连接到服务器程序S,但是每个机子的测试客户端连接数只能到6w多个,这个跟机子的情况有关,有的可以连到6.4万,有的更少;而此时服务器却支持了近20W个连接。

服务器程序S运行的主机地址为:192.168.4.220,监听端口为1883。
测试客户端程序C1运行的主机地址为:192.168.4.221
测试客户端程序C2运行的主机地址为:192.168.4.222
测试客户端程序C3运行的主机地址为:192.168.4.223
此时在测试客户端程序C1、C2、C3中一直创建新连接到服务器程序S,但是每个机子的测试客户端连接数只能到6w多个,这个跟机子的情况有关,有的可以连到6.4万,有的更少;而此时服务器却支持了近20W个连接。


答案是:
对于server:
      根据前面的描述,server将会为这三台测试机中的每个连接都创建一个socket进行通信,每个socket就是一个五元组:
      server程序中为C1建立的socket连接为(1025~1078之间的端口被其他程序占用了):
第一组
<192.168.4.221, 1078, 192.168.4.220, 1883>
<192.168.4.221, 1079, 192.168.4.220, 1883>
......
<192.168.4.221, 65535, 192.168.4.220, 1883>

      server程序中为C2建立的socket连接为(1025~1973)之间的端口被其他程序占用了):
第二组
<192.168.4.222, 1973, 192.168.4.220, 1883>
<192.168.4.222, 1974, 192.168.4.220, 1883>
......
<192.168.4.222, 65535, 192.168.4.220, 1883>

      server程序中为C3建立的socket连接为(1025~1623)之间的端口被其他程序占用了):
第三组
<192.168.4.223, 1623, 192.168.4.220, 1883>
<192.168.4.223, 1624, 192.168.4.220, 1883>
......
<192.168.4.223, 65535, 192.168.4.220, 1883>

      上述socket所对应的五元组中,每一组内部的五元组中,都是端口发生了变化,但是其他元素:源地址、目的地址、目的端口、协议都没有变化;

      这三组之间进行对比时,则变化的是源地址,其他元素:源端口、目的地址、目的端口、协议都没有变化(源端口可能不会全部重合,但是大部分都是一样的);

      由于五元组中任何一个成员发生了变化,也就是对应了一个全新的socket。
在server中,只需要为每个五元组socket产生一个文件描述符来标识进行区分即可,此时只要将所在机子的文件描述符限制值改大,只要超过20W,就可以让其支持这么多的socket连接了,

对于测试客户端:
以第一组为例:
      其产生的socket所对应的五元组为:
<192.168.4.221, 1078, 192.168.4.220, 1883>
<192.168.4.221, 1079, 192.168.4.220, 1883>
......
<192.168.4.221, 65535, 192.168.4.220, 1883>
      可以看到源地址、目的地址、目的端口、协议这4项是固定的,没有办法改变,所以它此时只能变化一个元素:源端口号!
      由于linux操作系统中port的范围有限,只能用1024~65535之间的,如果这之间的端口号再被别的程序占用一些,能用的就更少了,因此它只能支持6w左右的连接。
Logo

更多推荐