【转载】网络通讯socket链接数上限

http://blog.csdn.net/tgxallen/article/details/54947523

http://www.cppblog.com/aa19870406/archive/2012/07/15/183595.html

socket accept()返回的socket描述符的端口和listen描述符端口是同样的吗?

as you know,一个socket是由一个五元组来惟一标示的,即(协议,server_ip, server_port, client_ip, client_port)。只要该五元组中任何一个值不一样,则其表明的socket就不一样。这里忽略协议的区别,在同一协议的基础上,服务器端的listen socket的端口能够当作(server_ip, server_port, ***, ***),其中***是通配符,它跟任何一个client_ip, client_port值都不一样,能够简单当作是(0,0)对,固然实现不是这样的。这样在服务器端accept以后,返回的链接socket的四元组就是(server_ip, server_port, client_ip, client_port),这里的client_ip,client_port因链接的客户端的不一样而不一样。因此accept返回的socket和listen socket是不一样的,不一样之处就在于四元组中的客户端ip和port,而服务器端的server_ip和server_port仍是相同的,也就是accpet()函数返回的新的socket描述符的端口和listen端口是同样的。可使用getsockname()函数来查看它们之间的不一样。html

 

http://blog.csdn.NET/hanzengyi/article/details/5365029程序员

 

accept是又产生一个Socket端口吗?面试

      要写网络程序就必须用Socket,这是程序员都知道的。并且,面试的时候,咱们也会问对方会不会Socket编程?通常来讲,不少人都会说,Socket编程基本就是listen,accept以及send,write等几个基本的操做。是的,就跟常见的文件操做同样,只要写过就必定知道。编程

 

      对于网络编程,咱们也言必称TCP/IP,彷佛其它网络协议已经不存在了。对于TCP/IP,咱们还知道TCP和UDP,前者能够保证数据的正确和可靠性,后者则容许数据丢失。最后,咱们还知道,在创建链接前,必须知道对方的IP地址和端口号。除此,普通的程序员就不会知道太多了,不少时候这些知识已经够用了。最多,写服务程序的时候,会使用多线程来处理并发访问。windows

 

咱们还知道以下几个事实:缓存

     1.一个指定的端口号不能被多个程序共用。好比,若是IIS占用了80端口,那么Apache就不能也用80端口了。服务器

     2.不少防火墙只容许特定目标端口的数据包经过。网络

     3.服务程序在listen某个端口并accept某个链接请求后,会生成一个新的socket来对该请求进行处理。多线程

 

     因而,一个困惑了我好久的问题就产生了。若是一个socket建立后并与80端口绑定后,是否就意味着该socket占用了80端口呢?若是是这样的,那么当其accept一个请求后,生成的新的socket到底使用的是什么端口呢(我一直觉得系统会默认给其分配一个空闲的端口号)?若是是一个空闲的端口,那必定不是80端口了,因而之后的TCP数据包的目标端口就不是80了--防火墙必定会阻止其经过的!实际上,咱们能够看到,防火墙并无阻止这样的链接,并且这是最多见的链接请求和处理方式。个人不解就是,为何防火墙没有阻止这样的链接?它是如何断定那条链接是由于connet80端口而生成的?是否是TCP数据包里有什么特别的标志?或者防火墙记住了什么东西?并发

 

      后来,我又仔细研读了TCP/IP的协议栈的原理,对不少概念有了更深入的认识。好比,在TCP和UDP同属于传输层,共同架设在IP层(网络层)之上。而IP层主要负责的是在节点之间(End to End)的数据包传送,这里的节点是一台网络设备,好比计算机。由于IP层只负责把数据送到节点,而不能区分上面的不一样应用,因此TCP和UDP协议在其基础上加入了端口的信息,端口因而标识的是一个节点上的一个应用。除了增长端口信息,UPD协议基本就没有对IP层的数据进行任何的处理了。而TCP协议还加入了更加复杂的传输控制,好比滑动的数据发送窗口(Slice Window),以及接收确认和重发机制,以达到数据的可靠传送。无论应用层看到的是怎样一个稳定的TCP数据流,下面传送的都是一个个的IP数据包,须要由TCP协议来进行数据重组。

 

      因此,我有理由怀疑,防火墙并无足够的信息判断TCP数据包的更多信息,除了IP地址和端口号。并且,咱们也看到,所谓的端口,是为了区分不一样的应用的,以在不一样的IP包来到的时候可以正确转发。

 

     TCP/IP只是一个协议栈,就像操做系统的运行机制同样,必需要具体实现,同时还要提供对外的操做接口。就像操做系统会提供标准的编程接口,好比Win32编程接口同样,TCP/IP也必须对外提供编程接口,这就是Socket编程接口--原来是这么回事啊!

 

在Socket编程接口里,设计者提出了一个很重要的概念,那就是socket。这个socket跟文件句柄很类似,实际上在BSD系统里就是跟文件句柄同样存放在同样的进程句柄表里。这个socket实际上是一个序号,表示其在句柄表中的位置。这一点,咱们已经见过不少了,好比文件句柄,窗口句柄等等。这些句柄,实际上是表明了系统中的某些特定的对象,用于在各类函数中做为参数传入,以对特定的对象进行操做--这实际上是C语言的问题,在C++语言里,这个句柄其实就是this指针,实际就是对象指针啦。

 

如今咱们知道,socket跟TCP/IP并无必然的联系。Socket编程接口在设计的时候,就但愿也能适应其余的网络协议。因此,socket的出现只是能够更方便的使用TCP/IP协议栈而已,其对TCP/IP进行了抽象,造成了几个最基本的函数接口。好比create,listen,accept,connect,read和write等等。

 

如今咱们明白,若是一个程序建立了一个socket,并让其监听80端口,实际上是向TCP/IP协议栈声明了其对80端口的占有。之后,全部目标是80端口的TCP数据包都会转发给该程序(这里的程序,由于使用的是Socket编程接口,因此首先由Socket层来处理)。所谓accept函数,其实抽象的是TCP的链接创建过程。accept函数返回的新socket其实指代的是本次建立的链接,而一个链接是包括两部分信息的,一个是源IP和源端口,另外一个是宿IP和宿端口。因此,accept能够产生多个不一样的socket,而这些socket里包含的宿IP和宿端口是不变的,变化的只是源IP和源端口。这样的话,这些socket宿端口就能够都是80,而Socket层仍是能根据源/宿对来准确地分辨出IP包和socket的归属关系,从而完成对TCP/IP协议的操做封装!而同时,放火墙的对IP包的处理规则也是清晰明了,不存在前面设想的种种复杂的情形。

 

明白socket只是对TCP/IP协议栈操做的抽象,而不是简单的映射关系,这很重要!

 

http://blog.csdn.Net/zztfj/article/details/10103621http://blog.csdn.net/zztfj/article/details/10103621

 

 单机最大的TCP链接数及其修改
一个误解: 单个服务器程序可承受最大链接数“理论”上是“65535” .

   65535这个数字的由来,不少人想固然地将它与port最大值联系起来。的确,TCP的端口数,最大值确实为65535。可是,这并不表明一个服务器能够接受的链接数就是这个值。不少人之因此把这两个概念搞混淆是由于对socket和port没有更深的认识和理解。咱们先来回想一下服务器服务的前后过程:
一、服务器建立监听socket
二、与对外服务的端口号绑定
三、开始listen
四、客户端链接到服务器对应的port
五、服务器accept为新的客户端产生新的socket
六、基于这个新的socket与客户端交换数据。
从以上流程来看,最大值为65535的“端口号”这个重要的东东,咱们只用了一次,就是执行bind的时候!而之后建立的socket,说白了就是一个能够进行网络IO操做的HANDLE而已。经过查看该HANDLE的RemoteEndPoint能查看到远程客户端链接的IP和端口号(注意,该端口是远程客户端的端口),查看该HANDLE的LocalEndPoint能看到该Socket的Ip和端口就是该服务绑定的IP和端口。因此,accept的socket值与端口号无关,又何来65535的“理论”上限?

好了,已经弄明白了服务器端接收的客户端链接链接数不受最大端口号65535的限制。可是,在客户端,应用程序最多能够创建多少个TCP链接呢?以及如何调整系统参数来调整单机的最大TCP链接数。

Windows 下单机的TCP链接数有多个参数共同决定,下面一一介绍:

最大TCP链接数
[HKEY_LOCAL_MACHINE \System \CurrentControlSet \Services \Tcpip \Parameters]
TcpNumConnections = 0x00fffffe (Default = 16,777,214)

 

以上注册表信息配置单机的最大容许的TCP链接数,默认为 16M。这个数值看似很大,这个并非限制最大链接数的惟一条件,还有其余条件会限制到TCP 链接的最大链接数。

最大动态端口数
TCP客户端和服务器链接时,客户端必须分配一个动态端口,默认状况下这个动态端口的分配范围为 1024-5000 ,也就是说默认状况下,客户端最多能够同时发起3977 个Socket 链接。咱们能够修改以下注册表来调整这个动态端口的范围

[HKEY_LOCAL_MACHINE \System \CurrentControlSet \Services \Tcpip \Parameters]
MaxUserPort = 5000 (Default = 5000, Max = 65534)

 

最大TCB 数量
系统为每一个TCP 链接分配一个TCP 控制块(TCP control block or TCB),这个控制块用于缓存TCP链接的一些参数,每一个TCB须要分配 0.5 KB的pagepool 和 0.5KB 的Non-pagepool,也就说,每一个TCP链接会占用 1KB 的系统内存。

系统的最大TCB数量由以下注册表设置决定

[HKEY_LOCAL_MACHINE \System \CurrentControlSet \Services \Tcpip \Parameters]
MaxFreeTcbs = 2000 (Default = RAM dependent, but usual Pro = 1000, Srv=2000)

非Server版本,MaxFreeTcbs 的默认值为1000 (64M 以上物理内存)

Server 版本,这个的默认值为 2000。

也就是说,默认状况下,Server 版本最多同时能够创建并保持2000个TCP 链接。

最大TCB Hash table 数量
TCB 是经过Hash table 来管理的,下面注册表设置决定了这个Hash table 的大小

HKEY_LOCAL_MACHINE \System \CurrentControlSet \services \Tcpip \Parameters]
MaxHashTableSize = 512 (Default = 512, Range = 64-65536)

这个值指明分配 pagepool 内存的数量,也就是说,若是MaxFreeTcbs = 1000 , 则 pagepool 的内存数量为 500KB

那么 MaxHashTableSize 应大于 500 才行。这个数量越大,则Hash table 的冗余度就越高,每次分配和查找 TCP  链接用时就越少。这个值必须是2的幂,且最大为65536.

 

IBM WebSphere Voice Server 在windows server 2003 下的典型配置
这是IBM WebSphere Voice Server 的典型配置,你们能够作个参考。原文参见

IBM Web Sphere Voice Server 配置

 

•MaxUserPort = 65534 (Decimal)
•MaxHashTableSize = 65536 (Decimal)
•MaxFreeTcbs = 16000 (Decimal) 
这里咱们能够看到 MaxHashTableSize 被配置为比MaxFreeTcbs 大4倍,这样能够大大增长TCP创建的速度。

 

http://www.zhihu.com/question/30772664

单个链接消耗内存的地方.

 

第一个首先是socket buffer. read 和write 分别有一个, 默认大小在
  • /proc/sys/net/ipv4/tcp_rmem (for read)
  • /proc/sys/net/ipv4/tcp_wmem (for write)
默认大小都是87K和16K, 最低是4K和4K, 最高是2M,2M, 实际使用默认值最低也要保留8K,8K.

而后是逻辑IO缓冲区
就是好比你监听了recv事件 事件来了 你要有内存可用(通常都是socket创建起就分配好,断开才会释放的).
这个内存是本身写socket程序时候本身控制的, 最低也要4K,4K, 实际使用8K,8K至少.

如今设定一个优化方案和使用场景, 首先假设4G内存所有为空闲(系统和其余进程也要内存的....

假如网络包的大小均可以控制在4K如下, 假设全部链接的网络都不会拥堵, 或者拥堵时候的总量在4K如下:
一个链接的内存消耗是4+4+4+4=16K
4G/16K=26.2万并发

假如网络包的大小均可以控制在8K如下, 假设全部链接的网络都不会拥堵, 或者拥堵时候的总量在8K如下
一个socket的内存占用介于 24K ~ 32K之间, 保守的按照32K算 
4G/32K=13.1万并发, 这个在生产环境做为一个纯网络层面的内存消耗, 是能够做为参考的.

假如使用默认配置, 假如全部链接的网络都出现严重拥堵, 不考虑逻辑上的发送队列的占用,
使用默认配置是2M+2M+8+8 ~= 4M
4G/4M=1024并发 ( ...
若是考虑到发送队列也拥堵的话 本身脑补.


若是只是为了跑分 为了并发而优化, 没有常驻的逻辑缓冲区 而且socket的网络吞吐量很小而且负载平滑, 把socket buffer size设置系统最低.
那么是
4G/8K = 52.4万并发 这个应该是极限值了.
相关文章
相关标签/搜索