如何在Linux中创build很多(我的意思是很多)套接字?

我试图用不同的语言(C#,Java,C ++,PHP)来创build一个简单的程序来连接到一个服务器,所有的行为都是一样的。 所以我相信这个问题更多的是一个操作系统级的东西。

基本上我想程序连接到TCP套接字的服务器,并发送1个字节,然后closures套接字。 这需要每秒完成数千次,并持续一段时间。 这是为了对服务器进行基准testing。

到目前为止,在几千个客户端套接字之后,系统完全停止。 它只能在一分钟左右冷却后才能开始创build套接字。 我已经确定,在传输之后我已经closures了每个sockets。

现在,这类问题对像Apache这样的服务器很熟悉,其中的工具(如ab / siege)被build议使用keep-alive协议对Apache进行基准testing。 也就是说,创buildless量的TCP连接,但通过它们发出多个请求来达到基准testing的目的。 然而,在我们的情况下,这是不可能的,因为我们的专有服务器不提供HTTP服务,也不支持HTTP 1.1保持活动模式。

那么如何实现呢? 我已经检查了以下限制

  1. ulimit被设置为非常高的数字
  2. 通过将/proc/sys/net/ipv4/tcp_rw_recycle/proc/sys/net/ipv4/tcp_rw_reuse为1来消除TCP TIME_WAIT 。(我确实已经用netstat确认了没有TIME_WAIT套接字)
  3. 这与线程/进程数量的限制无关。 我已经尝试重新启动我的客户端应用程序,它是一样的。 一旦操作系统拒绝新的套接字,没有任何帮助。

PS。 这不是服务器端的限制。 我们通过购买另一个盒子并在第一个客户端盒子拒绝插入新套接字时运行相同的客户端代码来testing这一点。 服务器处理得很好。 我们不想购买5-10盒,并在它们之间旋转来克服这个问题。

OS:Fedora 10 Linux 2.6.24-23-xen#1 SMP

老笑话:男人去看医生,说“医生,当我这样做的时候疼,”把他的手臂扭到一个奇怪的位置。

医生回答:“好吧,别这样做 !”

看,你在做什么是一个非常不自然的过程。 建立TCP连接需要握手,每个消息传输的字节数远远超过一个字节。 安装和拆卸时间将是重要的。 你很可能正在使用与握手相关的内核资源; 果然,如果你让它独自一人,不再拍掌,它终将迎头赶上。

那么,你究竟想要衡量什么? 你真的想做什么? 如果你真的想一次发送一个字节 – 神不准 – 至少考虑使用udp; 没有可怕的设置/拆解。 与开销相比,它仍然非常低效 – 即使是UDP数据包也需要类似20个字节的帧,但效果会更好。

看看理查德·琼斯的文章, 一个百万用户彗星与Mochiweb应用程序,第3部分 。 这是关于在Erlang实现一个Comet应用程序,但是“把它变成100万”部分描述了他如何对他的服务器进行基准测试; 它以“从一个主机创建一百万个tcp连接是非常重要的”语句打开。 这应该让你知道你在做什么。

你有没有尝试在套接字上设置标志SO_REUSEADDR?

你有没有可能跑出港口? 除非您愿意在循环中调用bind()以查找下一个空闲端口,否则您只能获得5000 – 1024个端口。

将端口号为0的bind()返回1024-5000范围内的空闲端口。 绑定()与指定的端口获取该端口(如果可用)。

 int bindnextport(int s, struct sockaddr sa) { static int nextport = 1025; int lastport; lastport = nextport; do { sa.sa_data[0] = nextport >> 8; sa.sa_data[1] = nextport & 255; if (!bind(s, &sa, sizeof(sa)) return 0; ++nextport; if (nextport >= 65536) nextport = 1024; } while (lastport != nextport); return 1; } 

连接然后发送1个字节不是任何东西的基准,除了TCP协议本身。 正如查理·马丁上面所说,大部分时间都是浪费连接,然后断开插座。

我明白你想要基准测试,但这真的是一个很好的代表你的应用程序呢? 你真的要建立一个连接发送1个字节吗?

nginx http服务器声称能够保持10,000个不活动的HTTP保持连接。 你可以看看他们是怎么做的 。