一旦超过listen(),程序如何等待传入连接

时间:2012-04-03 12:58:54

标签: c sockets

我正在学习c语言中的套接字编程,并试图理解listen()在代码中究竟是做什么的。据我所知,它定义了可以为accept()排队的最大连接数,但除此之外,我似乎无法理解它还在做什么。

根据我所学的文字,

  

listen()等待传入的连接。   Accept()获取您正在侦听的端口上的挂起连接() ing

查看执行流程,我发现listen()实际上只被调用一次,之后只有accept()处理任何新的连接。然后,服务器如何监听未来的请求,如果我们进入接受循环后,从不调用listen()。?

                       +----------+
                       |socket()  |
                       +----------+

                       +----------+
                       |bind()    |
                       +----------+

                       +----------+
                       |listen()  |
                       +----------+
                       +----------+
                       |while(1)  |
                       |----------|
                       |accept()  |
                       |          |
                       |          |
                       +----------+

以下是我正在处理的代码:

/*Server*/

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>

int main()
{
    int sockfd, newsock;
    char buffer[200];
    memset(buffer, 0, sizeof(buffer));

    /*Creating a new socket*/
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("Socket error");
        exit(1);
    }

    /*Creating socket address structure*/
    struct sockaddr_in server_addr, client_address;

    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(7200);
    server_addr.sin_addr.s_addr = inet_addr("192.168.1.2");
    bzero(&(server_addr.sin_zero),8);

    /*Binding*/
    if(bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
    {
        perror("Bind error");
        exit(1);
    }

    /*Listening for new connection; maximum 5*/
    if(listen(sockfd, 5) < 0)
    {
        perror("Listen error");
    }


    while(1)
    {
        socklen_t len = sizeof(client_address);

        if((newsock = accept(sockfd, (struct sockaddr *)&client_address, &len)) < 0)
        {
            perror("Accept error");
            exit(1);
        }

        int i;
        if((i = read(newsock, buffer, sizeof(buffer))) < 0)
        {
            perror("Receive error");
            exit(1);
        }
        if(i == 0)
        {
            printf("Socket closed remotely\n");
        }
        if(i > 0)
        {
            printf("received %d bytes\n",i);
            printf("data: %s",buffer);
        }

        close(newsock);
    }
    close(sockfd);

    return 0;
}

4 个答案:

答案 0 :(得分:5)

  

listen()等待传入的连接。

这只是一种误导性的简化。此系统调用标记用于侦听的套接字。这意味着它通知操作系统嘿,注意这个套接字,你将接收到它的连接请求

真正的等待功能是accept功能等待传入连接。每次调用它时(在阻塞上下文中),都会发生以下两种情况之一:

  • 如果存在未接受的连接(由第二个listen参数控制)accept只提取一个并且已完成
  • 否则它实际上等待连接在返回之前变为可用

答案 1 :(得分:2)

listen()功能等待连接;它(a)通知内核套接字将接受连接并且(b)设置backlog参数 - 内核在拒绝新连接之前将排队的连接数。 listen()只被调用一次,因为它只是设置了东西。

accept()函数处理新连接。从手册页:

   The accept() function shall extract the first connection on  the  queue
   of  pending  connections, create a new socket with the same socket type
   protocol and address family as the specified socket, and allocate a new
   file descriptor for that socket.

因此,listen()设置套接字,内核处理连接建立,accept()从队列中拉出连接并使它们可用于您的代码。

答案 2 :(得分:1)

listen的调用只是订阅您的流程,以便稍后交付最终的连接。实际工作在内核空间完成,对accept的调用只是获取已建立连接的描述符。

答案 3 :(得分:1)

listen()将套接字置于侦听模式。之后它会永远倾听,因此您无需再次致电listen()。此后,您只需拨打accept()即可接听正在收听的连接,每次连接一次。