c++ - C/C++:socket() 创建在循环中失败,打开的文件太多
问题描述
我正在实现一个客户端-服务器 TCP 套接字应用程序。Client
位于 OpenWRT Linux 路由器(基于 C)上,并以某种频率重复并循环写入套接字上的一些数据。它Server
位于 Linux Ubuntu 机器(基于 C/C++)上,并根据数据到达速度循环读取数据。
问题:运行Server
然后Client
,服务器不断读取新数据。双方工作良好,直到数据传递的数量(连接数)达到 1013。之后,Client
卡在socket(AF_INET,SOCK_STREAM,0)
with socket creation failed...: Too many open files
。显然,客户端上打开fd
方法的数量ulimit -n = 1024
。
我放置了代码片段,其中显示了Server.cpp
and的循环结构Client.c
:
服务器.c:
// TCP Socket creation stuff over here (work as they should):
// int sock_ = socket() / bind() / listen()
while (1)
{
socklen_t sizeOfserv_addr = sizeof(serv_addr_);
fd_set set;
struct timeval timeout;
int connfd_;
FD_ZERO(&set);
FD_SET(sock_, &set);
timeout.tv_sec = 10;
timeout.tv_usec = 0;
int rv_ = select(sock_ + 1, &set, NULL, NULL, &timeout);
if(rv_ == -1){
perror("select");
return 1;
}
else if(rv_ == 0){
printf("Client disconnected.."); /* a timeout occured */
close (connfd_);
close (sock_);
}
else{
connfd_ = accept (sock_,(struct sockaddr*)&serv_addr_,(socklen_t*)&sizeOfserv_addr);
if (connfd_ >= 0) {
int ret = read (connfd_, &payload, sizeof(payload)); /* some payload */
if (ret > 0)
printf("Received %d bytes !\n", ret);
close (connfd_); /* Keep parent socket open (sock_) */
}else{
printf("Server acccept failed..\n");
close (connfd_);
close (stcp.sock_);
return 0;
}
}
}
客户端.cpp:
while (payload_exist) /* assuming payload_exist is true */
{
struct sockaddr_in servaddr;
int sock;
if (sock = socket(AF_INET, SOCK_STREAM, 0) == -1)
perror("socket creation failed...\n");
int one = 1;
int idletime = 2;
setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one));
setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &idletime, sizeof(idletime));
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr("192.168.100.12");
servaddr.sin_port = htons(PORT); /* some PORT */
if (connect (sock, (struct sockaddr*)&servaddr, sizeof(servaddr)) != 0){
perror("connect failed...");
return 1;
}
write(sock, (struct sockaddr*)&payload, sizeof(payload)); /* some new payload */
shutdown(sock,SHUT_WR);
bool serverOff = false;
while (!serverOff){
if(read(sock, &res, sizeof(res)) < 0){
serverOff = true;
close(sock);
}
}
}
注意:每一个payload
动作800 bytes
都会被完全传输write
。在 下定义了这两个代码int main()
后,客户端会不断创建套接字并发送数据,另一方面,服务器会接收所有数据,close()
并且如果客户端终止,则会自动离开,因为使用select()
. 但是,如果我不通过Client
检查一些打印日志来终止.Server
socket creation failed...: Too many open files
更新:
按照 Steffen Ullrich 提到的观点,事实证明,客户端套接字fd
没有泄漏,并且fd
原始循环中存在第二个(保持打开状态)使得ulimit
超出限制。
解决方案
if(read(sock, &res, sizeof(res)) < 0){
serverOff = true;
close(sock); /********* Not actually closing sock *********/
}
您对连接结束的检查是错误的。
read
如果对方关闭连接并且<0
仅在出错时返回 0。
if (sock = socket(AF_INET, SOCK_STREAM, 0) == -1)
perror("socket creation failed...\n");
鉴于C中运算符的优先级,这基本上是说:
sock = ( socket(AF_INET, SOCK_STREAM, 0) == -1) )
if (sock) ...
假设这socket(...)
不会返回错误而是文件描述符(即>=0
),比较将是错误的,因此这实质上是sock = 0
在泄漏文件描述符时如果 fd 返回的socket
是>0
。
推荐阅读
- c++ - 如何使用指针访问这个二维数组的元素?
- c# - Linux 上的 C# DotNet Entity Framework Core Migrations 错误
- unity3d - 统一引擎代码和统一脚本代码有什么区别?
- javascript - 如何使用javascript删除字典列表中列表中的值
- python - Odoo 14/Python:FileNotFoundError:[Errno 2] 没有这样的文件或目录:'/events/img\\models'
- ios - 是否有任何机制以安全的方式向 iOS 应用程序传递秘密
- javascript - 创建两个具有相同功能但用于不同元素的按钮
- git - “git add .”和“git add -A”有区别吗?
- python - 如何使用网格布局 Python Tkinter 在小部件之间平均分配空间
- python - 调整图像文件夹的大小