Hi:
春哥,根据您给我的链接中的代码,如下:
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/resource.h>
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
const char *addrs[] = { “127.0.0.1” };
int
main (int argc, char **argv)
{
struct rlimit rl;
int *sockets;
int nsockets = 120000;
int c, i;
rl.rlim_cur = rl.rlim_max = nsockets + 10;
if (setrlimit(RLIMIT_NOFILE, &rl) == -1) {
perror("setrlimit");
exit(1);
}
if ((sockets = (int *) malloc(nsockets * 2 * sizeof(int))) == NULL) {
perror("malloc");
exit(1);
}
for (i = 0; i < nsockets; i++) {
struct addrinfo *aitop, ai_hints = { .ai_family = AF_INET,
.ai_socktype = SOCK_STREAM, .ai_flags = AI_PASSIVE };
const char *addr = addrs[i % (sizeof(addrs) / sizeof (addrs[0]))];
const char *portstr = "0";
getaddrinfo(addr, portstr, &ai_hints, &aitop);
sockets[i] = socket(AF_INET, SOCK_STREAM, 0);
if (bind(sockets[i], aitop->ai_addr, aitop->ai_addrlen) == -1) {
fprintf(stderr, "Error binding %s, for %s : %d\n",
strerror(errno), addr, portstr);
} else
fprintf(stderr, "ok addr: %s, i: %d portstr: %s\n", addr, i, portstr);
free(aitop);
}
printf("%i socket pairs created, check memory. Sleeping 10 sec.\n", i);
sleep(10);
exit(0); }
得到的结果:
ok addr: 127.0.0.1, i: 28218 portstr: 0
ok addr: 127.0.0.1, i: 28219 portstr: 0
ok addr: 127.0.0.1, i: 28220 portstr: 0
ok addr: 127.0.0.1, i: 28221 portstr: 0
ok addr: 127.0.0.1, i: 28222 portstr: 0
ok addr: 127.0.0.1, i: 28223 portstr: 0
ok addr: 127.0.0.1, i: 28224 portstr: 0
ok addr: 127.0.0.1, i: 28225 portstr: 0
ok addr: 127.0.0.1, i: 28226 portstr: 0
ok addr: 127.0.0.1, i: 28227 portstr: 0
ok addr: 127.0.0.1, i: 28228 portstr: 0
ok addr: 127.0.0.1, i: 28229 portstr: 0
ok addr: 127.0.0.1, i: 28230 portstr: 0
ok addr: 127.0.0.1, i: 28231 portstr: 0
ok addr: 127.0.0.1, i: 28232 portstr: 0
Error binding Address already in use, for 127.0.0.1 : 4197267
Error binding Address already in use, for 127.0.0.1 : 4197267
而修改代码
const char *addrs[] = { “127.0.0.1”,“127.0.0.2” };
后得到的结果是:
ok addr: 127.0.0.2, i: 56455 portstr: 0
ok addr: 127.0.0.1, i: 56456 portstr: 0
ok addr: 127.0.0.2, i: 56457 portstr: 0
ok addr: 127.0.0.1, i: 56458 portstr: 0
ok addr: 127.0.0.2, i: 56459 portstr: 0
ok addr: 127.0.0.1, i: 56460 portstr: 0
ok addr: 127.0.0.2, i: 56461 portstr: 0
ok addr: 127.0.0.1, i: 56462 portstr: 0
ok addr: 127.0.0.2, i: 56463 portstr: 0
ok addr: 127.0.0.1, i: 56464 portstr: 0
ok addr: 127.0.0.2, i: 56465 portstr: 0
Error binding Address already in use, for 127.0.0.1 : 4197277
Error binding Address already in use, for 127.0.0.2 : 4197277
其中:
[root@centos-64bit ~]# cat /proc/sys/net/ipv4/ip_local_port_range
32768 61000
恰好,程序修改之前得到的结果:28232 = 61000 - 32768
修改之后的结果:56465 = 2*28232 - 1
以上是不是说明依靠多个本地 IP 可以成倍提高可用的端口数目呢?
Hello!
2014-11-12 17:03 GMT-08:00 yurnero:
是不是漏了链接了【因为 Linux 内核实现上的问题和限制 [1]】,
嗯,我漏了链接:
http://aleccolocco.blogspot.com/2008/11/ephemeral-ports-problem-and-solution.html简单说来,如果 bind() 时让 Linux 系统自己分配临时端口,则内核会在查找时并不使用 IP 地址作为查找的
key,而只是全局地找可用的端口号,于是没法实现靠多个本地 IP 来成倍提高可用的端口数目。
另外复用连接池也就是keepalive吧?
是。长连接的一个问题是可能会导致大量的空闲连接而造成资源浪费,解决的办法是在客户端(或者服务器端)设置最大空闲等待时间,超过了就自动关闭连接。比如
ngx_lua 的 cosocket 就支持客户端做这个空闲超时保护。貌似 nginx 自己的
ngx_http_upstream_keepalive_module 并不支持这么搞,需要自己 patch 或者直接在服务器端做了。
Regards,
-agentzh
--
--