打开和关闭无限套接字时打开的文件太多

时间:2012-11-02 11:19:16

标签: c sockets

我在这个网站上搜索过这个问题。

我的计划方案是:

  • 有一台服务器始终侦听来自客户端的请求。
  • 有一个客户端总是在2秒内从服务器请求char

收到错误消息:

  

程序运行大约1024次后,socket()函数发生了太多的打开文件。

我目前的解决方案是增加打开文件的数量: "ulimit -n 5000",但我不认为这是一个完美的解决方案,因为它会让程序运行5000次。

那么,有没有人有更好的解决方案?

环境:

  • ubuntu 10
  • c语言

我的代码如下:

客户端:

    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);

2 个答案:

答案 0 :(得分:3)

您正在关闭客户端中的套接字但从未关闭它。这不是一回事。

答案 1 :(得分:3)

shutdown()close()之间存在很大差异。当你“关闭”一个套接字时,你将它置于一个“半闭”的状态,在这种状态下仍然可以通过连接发送或接收(取决于你关闭的那一半)。

套接字仍然有效,TCP仍然维护有关连接的状态信息,并且端口仍然是“打开”,并且套接字/文件描述符仍然分配给您的进程。

当你致电close()时,套接字/文件描述符是免费的,但其余的仍然。 TCP必须持有一段时间的资源,通常是2分钟(这取决于谁做了关闭和其他一些事情),在此期间状态信息和本地端口本身仍处于“使用中”。

因此,即使您的进程可能不再超出文件描述符限制,理论上也可能会使网络堆栈的资源饱和,而无法打开新连接。