我发现在Python中可以打开将近8156个套接字连接,但是我调用resource.getrlimit(resource.RLIMIT_NOFILE) => (1024, 1048576)
这是否意味着文件描述符限制是1024?如果不是,为什么数字是8000+,而不是接近1048576?
但是在同样的资源条件下,我在C中只能打开将近1024个套接字连接
我的操作系统是ubuntu,Python版本是3.6.8ulimit -n is 1024 ulimit -Hn is 1048576
我刚才又测试了一下,如果我在C代码中把RLIMIT_NOFILE软限制设置成和硬限制一样,套接字连接数可以增加到8000+,和Python一样,但是不能再增加了,那么相对于什么呢?
代码在这里,C++服务器和Python服务器,它们做同样的事情,侦听和接受套接字,计数
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <errno.h>
#include <sys/resource.h>
#define IP_ADDRESS "0.0.0.0"
#define PORT 20004
int main()
{
// get, set and check RLIMIT_NOFILE
struct rlimit res;
getrlimit(RLIMIT_NOFILE, &res);
printf("%ld %ld\n", res.rlim_cur, res.rlim_max);
res.rlim_cur = res.rlim_max - 1;
int rset = setrlimit(RLIMIT_NOFILE, &res);
printf("Result : %d\n", rset);
getrlimit(RLIMIT_NOFILE, &res);
printf("%ld %ld\n", res.rlim_cur, res.rlim_max);
int sock;
struct sockaddr_in addr;
int yes = 1;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
printf("Create Socket Failed::%d\n", errno);
return -1;
}
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
{
printf("Set Socket Opt Failed::%d\n", errno);
return -1;
}
memset(addr.sin_zero, 0x00, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr( IP_ADDRESS );
addr.sin_port = htons(PORT);
if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1)
{
printf("Bind Error::%d\n", errno);
return -1;
}
if(listen(sock, 5) == -1)
{
printf("Listen Error::%d\n", errno);
return -1;
}
int n = 1;
while(1) {
int cli_sock = accept(sock, NULL, NULL);
if(cli_sock != -1) {
printf("current connect : %d\n", n);
n++;
} else {
printf("Accept Failed");
break;
}
}
}
import socket
import resource
(_, hard) = resource.getrlimit(resource.RLIMIT_NOFILE)
resource.setrlimit(resource.RLIMIT_NOFILE, (hard - 1, hard))
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_address = ('localhost', 20004)
server.bind(server_address)
server.listen(5)
l = []
while(1):
try:
s = server.accept()
except Exception as e:
print(e)
break
else:
l.append(s)
print("current connection : ", len(l))
这是测试客户端,只需创建客户端套接字并进行连接和计数
import socket
TEST_PORT = 20004
l = []
while(1):
try:
fd = socket.socket()
fd.connect(("0.0.0.0", TEST_PORT))
except Exception as e:
print(e)
break
else:
l.append(fd)
print(len(l))
print(len(l))
所有这些代码我运行在正常用户模式,而不是根用户我的CPU是i5 6200U@2. 3Ghz,RAM是8GB
1条答案
按热度按时间lvmkulzt1#
一个进程可以打开的文件描述符的最大数量由
RLIMIT_NOFILE
资源限制的软限制决定。资源限制可以通过在C++中调用getrlimit(RLIMIT_NOFILE)
或在Python中调用resource.getrlimit(resource.RLIMIT_NOFILE)
来获取。当您将软限制设置为与硬限制相同的值时,可以打开的套接字连接数将增加到8000+,但不能再增加。这是因为硬限制是一个不能超过的硬编码值。
在您的例子中,您可以在Python中打开8156个套接字连接,这高于1024的软限制。这是因为Python解释器使用文件描述符来处理其他系统资源,例如除了套接字之外的管道。Python解释器可以使用的文件描述符的确切数量可能取决于系统的实现和配置。但是它通常高于软限制。
产生这种差异的原因是系统、库或其他内部进程使用了一些文件描述符,当达到最大限制时,系统会返回错误,例如C中的
EMFILE
和Python中的socket.error
。可以打开的套接字连接的确切数量取决于各种因素,如操作系统和硬件规格。此外,可能还有其他系统资源限制了可以打开的套接字连接的数量,如可用内存量。