如何在不设置 ulimit -n 的情况下解决套接字程序打开太多文件的错误
How to Solve Too Many Files Open Error from Socket Program without Setting ulimit -n
我目前正在用C++编写套接字服务器和客户端。我的目标是让服务器保持运行,而客户端应该在从服务器发送和接收消息时终止。
一切正常,直到客户端被调用大约 1000 次,并因打开文件过多错误而崩溃。我发现原因是ulimit -n的设置,其默认值为 1024。
我找到的大多数解决方案都告诉我们设置更高的 ulimit 值。但是,我不确定这是否正确:
- 这可能意味着我的代码中存在错误
- ulimit是为了保护我们的机器,设置得太高就像禁用保护一样
- 仍然有机会达到极限,假设服务器运行数周或数月,问题没有解决
我在网络上尝试了一些套接字示例,但它们有类似的问题,例如在这里。
问题:
- 有什么方法可以避免此错误吗?代码中有什么问题吗?
- 1048576说,设置 ulimit -n 是一个高值有害吗?
谢谢。
我的工作代码如下:
服务器.cpp:
#include <iostream>
#include <string.h>
#include <sys/socket.h> //sockaddr
#include <sys/un.h> //for sockadder_un
#include <errno.h>
#include <unistd.h> //unlink
#include <signal.h> //for catching ctrl+c
bool keep_running = true;
void terminate(int i) {
keep_running = false;
}
int main(int argc, char** argv[]) {
//--catch ctrl+c signal
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = terminate;
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGINT, &sigIntHandler, NULL);
//--create socket
int socket_fd_server = socket(AF_UNIX, SOCK_STREAM, 0);
if (socket_fd_server >= 0) {
std::cout << "Server socket created" << std::endl;
}
else {
std::cout << "Server socket failed to create, errno: " << errno << std::endl;
}
//--bind server
sockaddr_un address_server;
address_server.sun_family = AF_UNIX;
strcpy(address_server.sun_path, "./socket-server");
unlink(address_server.sun_path); //delete socket file if exists
//will create a socket file, if already exist, errno=98
if (bind(socket_fd_server, (sockaddr*)&address_server, sizeof(address_server)) >= 0) {
std::cout << "Server bound" << std::endl;
}
else {
std::cout << "Server failed to bind, errno: " << errno << std::endl;
return 1;
}
//--mark socket as passive socket (listen)
if (listen(socket_fd_server, 100) >= 0) {
std::cout << "Start to listen" << std::endl;
}
else {
std::cout << "Failed to listen, errno: " << errno << std::endl;
}
//--
sockaddr_un address_client;
char message_sent[] = {"message from server to client"};
char message_received[100] = {};
while (keep_running) {
unsigned int len = sizeof(address_client);
int socket_fd_client = accept(socket_fd_server, (sockaddr*)&address_client, &len);
send(socket_fd_client, message_sent, sizeof(message_sent), 0);
std::cout << "Server sent message: " <<message_sent << std::endl;
recv(socket_fd_client, message_received, sizeof(message_received), 0);
std::cout << "Server received message: " <<message_received << std::endl;
}
std::cout << "Leave while loop" << std::endl;
unlink(address_server.sun_path);
close(socket_fd_server);
return 0;
}
客户端.cpp:
#include <iostream>
#include <string.h>
#include <sys/types.h> //see NOTES in http://www.linuxhowtos.org/manpages/2/connect.htm
#include <sys/socket.h> //sockaddr
#include <sys/un.h> //for sockadder_un
//#include <netinet/in.h> //for sockadder_in
#include <unistd.h> //close
#include <errno.h>
int main(int argc, char** argv[]) {
//--create socket
int socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (socket_fd >= 0) {
std::cout << "Client socket created" << std::endl;
}
else {
std::cout << "Client socket failed to create, errno: " << errno << std::endl;
}
//--connection
sockaddr_un address_un;
address_un.sun_family = AF_UNIX;
//address_un.sun_path = "./SocketServer";
strcpy(address_un.sun_path, "../SocketServer/socket-server");
if (connect(socket_fd, (sockaddr*)&address_un, sizeof(address_un)) == 0) {
std::cout << "Client connected" << std::endl;
}
else {
std::cout << "Client failed to connect, errno: " << errno << std::endl;
}
//--send message
//char message_sent[] = {"test send message"};
std::string message_sent = "test send message";
if (send(socket_fd, message_sent.c_str(), sizeof(message_sent), 0) > 0) {
std::cout << "Message: " << message_sent << " sent" << std::endl;
}
else {
std::cout << "Message: " << message_sent << " not sent, errno: " << errno << std::endl;
}
//--receive message_sent
char message_received[100] = {}; // = "test receive message";
if (recv(socket_fd, message_received, sizeof(message_received), 0) > 0) {
std::cout << "Message: " << message_received << " received" << std::endl;
}
else {
std::cout << "Message: " << message_received << " not received, errno: " << errno << std::endl;
}
//--close
close(socket_fd);
return 0;
}
顺便说一句,这仅在服务器以 bash 运行时发生。如果服务器在 Eclipse 调试器中运行,则它可以超过 1024 次调用。我不知道为什么。
你漏了套接字。尝试一些错误检查。这里还不够。如果recv()
返回零,请关闭套接字。如果返回 -1 并且errno
不EAGAIN/EWOULDBLOCK
,请关闭套接字。如果send()
返回 -1,请关闭套接字。
在服务器中,您没有关闭您接受这样做的客户端的文件描述符
while (keep_running) {
unsigned int len = sizeof(address_client);
int socket_fd_client = accept(socket_fd_server, (sockaddr*)&address_client, &len);
send(socket_fd_client, message_sent, sizeof(message_sent), 0);
std::cout << "Server sent message: " <<message_sent << std::endl;
recv(socket_fd_client, message_received, sizeof(message_received), 0);
std::cout << "Server received message: " <<message_received << std::endl;
close(socket_fd_client); //close the file descriptor
}
相关文章:
- WINAPI 注册应用程序重新启动时不清除打开的套接字
- 在 1 个服务器 n 客户端套接字 C++ MFC 应用程序中更新数据的客户端
- 如何使用winsock在c++应用程序中实现安全套接字通信
- 如何在不设置 ulimit -n 的情况下解决套接字程序打开太多文件的错误
- 具有多线程应用程序的 Nanomsg 无阻塞双向套接字
- 我正在编写一个简单的客户端套接字应用程序,但在连接后服务器收到一个空缓冲区
- 套接字 UDP - 程序在接收处停止
- 防止客户端套接字程序崩溃CPP Google Protobuf
- Linux 套接字程序只是冻结而没有错误
- Visual Studio 中的套接字 c++ 应用程序无法通过两台计算机之间的以太网连接工作
- 强制终止和重新生成 TCP 套接字应用程序时无法重用端口
- C :如何使用log4cplus的套接字应用程序将日志发送到Logstash服务器
- 多连接客户端套接字应用程序C++
- QSocketNotifier:不能从另一个线程启用或禁用套接字通知程序
- 要打开以供C++中的应用程序最佳使用的并行套接字/TCP连接数
- 如果您不编写 Web 应用程序,并且您的客户端不是浏览器,那么 Web 套接字相对于常规套接字的优势是什么?
- 套接字应用程序无法正常工作
- 使用无效套接字调用boost::asio::write()使我的Blackberry 10应用程序崩溃
- Boost ASIO UDP 套接字async_receive_from不调用处理程序
- 通过网络中的套接字进行文件传输时,该程序中的文件传输错误是什么