我在这个网站上搜索过这个问题。
我的计划方案是:
char
收到错误消息:
程序运行大约1024次后,socket()函数发生了太多的打开文件。
我目前的解决方案是增加打开文件的数量:
"ulimit -n 5000"
,但我不认为这是一个完美的解决方案,因为它会让程序运行5000次。
那么,有没有人有更好的解决方案?
环境:
我的代码如下:
客户端:
int sockfd;
struct sockaddr_in address;
int socket_port = 9734;
while (1) {
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
DieWithSystemMessage("socket() failed");//<<===========Too many open files
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr("127.0.0.1");
address.sin_port = socket_port;
//Establish the connection to the server
if ((connect(sockfd, (struct sockaddr *) &address, sizeof(address)))
< 0)
DieWithSystemMessage("connect() failed");
if (rename_count % 2 == 0)
ch = 'A';
else if (rename_count % 2 == 1)
ch = 'B';
else
ch = 'E';
ssize_t numBytes = send(sockfd, &ch, strlen(&ch), 0);
if (numBytes < 0)
DieWithSystemMessage("send() failed");
else if (numBytes != strlen(&ch))
DieWithUserMessage("send()", "sent unexpected number of bytes");
//fflush(sockfd);
shutdown(sockfd, SHUT_RDWR);
rename_count++;
}
服务器:
int server_sockfd, client_sockfd;
int server_len, client_len;
socklen_t clntAddrLen;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
uint64_t start_time_micro, end_time_micro;
int socket_num = 9734;
server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (server_sockfd < 0)
DieWithSystemMessage("socket() failed");
memset(&server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr("127.0.0.1");
server_address.sin_port = socket_num;
if ((bind(server_sockfd, (struct sockaddr *) &server_address,
sizeof(server_address))) < 0)
DieWithSystemMessage("bind() failed");
if ((listen(server_sockfd, 5)) < 0)
DieWithSystemMessage("listen() failed");
while (1) {
char ch;
printf("\nserver waiting\n");
//accept a connect
clntAddrLen = sizeof(client_address);
client_sockfd = accept(server_sockfd,
(struct sockaddr *) &client_address, &clntAddrLen);
if (client_sockfd < 0)
DieWithSystemMessage("accept() failed");
//reading and writing through client side
ssize_t numBytesRcvd = recv(client_sockfd, &ch, 1, 0);
if (numBytesRcvd < 0)
DieWithSystemMessage("recv() failed");
if (ch == 'A') {
rename_num = 0;//printf("A\n");
} else if (ch == 'B') {
rename_num = 1;//printf("B\n");
} else
;
printf("%d. Got it!!!\n", i);
close(client_sockfd);
}
close(server_sockfd);
答案 0 :(得分:3)
您正在关闭客户端中的套接字但从未关闭它。这不是一回事。
答案 1 :(得分:3)
shutdown()
和close()
之间存在很大差异。当你“关闭”一个套接字时,你将它置于一个“半闭”的状态,在这种状态下仍然可以通过连接发送或接收(取决于你关闭的那一半)。
套接字仍然有效,TCP仍然维护有关连接的状态信息,并且端口仍然是“打开”,并且套接字/文件描述符仍然分配给您的进程。
当你致电close()
时,套接字/文件描述符是免费的,但其余的仍然。 TCP必须持有一段时间的资源,通常是2分钟(这取决于谁做了关闭和其他一些事情),在此期间状态信息和本地端口本身仍处于“使用中”。
因此,即使您的进程可能不再超出文件描述符限制,理论上也可能会使网络堆栈的资源饱和,而仍无法打开新连接。