代码之家  ›  专栏  ›  技术社区  ›  Bill the Lizard

如何创建一个一次只接受一个连接的TCP服务器?[闭门]

  •  8
  • Bill the Lizard  · 技术社区  · 16 年前

    我试图通过在 listen 函数设置为0和1,但这两个值似乎都不起作用。第一个客户端按预期进行连接,但在第一个客户端完成时,任何后续客户端都会阻塞。真正让我困惑的是,它们不会阻止连接到服务器,而是在第一次读取时阻止。

    我曾经 the code here

    9 回复  |  直到 16 年前
        1
  •  8
  •   Brian R. Bondy    16 年前

    当您接受连接时,将创建一个新套接字。旧的仍然用于监听将来的连接。

    与在accept之后立即关闭新的accepted套接字相比,您所寻找的是否存在净差异?当客户端尝试使用其套接字时(或者如果它已经在服务器上等待读取调用,则立即使用),最后一个错误是:服务器主动关闭连接。

        2
  •  4
  •   Johannes Weiss    16 年前

    别这样 fork() 之后 accept() .

    while(1) {
        listen()
        accept()
        *do something with the connection*
        close()
    }
    
        3
  •  4
  •   Chris AtLee    16 年前

    您可以在接受第一个连接后关闭正在侦听连接的原始套接字。我不知道您使用的套接字类是否允许您这样做。

        4
  •  3
  •   DaClown    16 年前

        5
  •  1
  •   Kuyo    14 年前

    因为您希望一次只允许一个连接,所以您可以只接受连接,然后在检测到您已经在处理另一个连接时关闭新接受的套接字。

    我认为应该是监听插座被关闭。 之后就不能再建立连接了。

        6
  •  0
  •   Nathan Fellman    16 年前

    如果可以控制客户端,则可以使套接字不阻塞。在这种情况下,它们将返回错误消息 EINPROGRESS

    我仍然在寻找如何将套接字更改为非阻塞。如果有人知道如何即兴回答,请随意编辑答案。

        7
  •  0
  •   royatl    16 年前

        8
  •  0
  •   sth    16 年前

    您可能有套接字选项 TCP_DEFER_ACCEPT 在监听插座上设置:

    TCP_DEFER_ACCEPT (since Linux 2.4)
        Allows  a  listener to be awakened only when data arrives on the socket.
        Takes an integer value (seconds), this can bound the maximum  number  of
        attempts  TCP  will make to complete the connection.  This option should
        not be used in code intended to be portable.
    

    我假设这会导致您描述的效果,即连接客户端不会阻塞 connect ,但在随后的 read . 我不确定什么是选项默认设置,以及应该设置什么来禁用此行为,但值为零可能值得一试:

    int opt = 0;
    setsockopt(sock, IPPROTO_TCP, TCP_DEFER_ACCEPT, &opt, sizeof(opt));
    
        9
  •  0
  •   michas    9 年前

    据我所知,不可能只监听一个连接。

    syn 收到数据包后,内核将该“连接”放在等待队列中,用 syn/ack ack accept() 呼叫(详情请参阅 here

    在linux上,backlog参数仅限制接受队列的大小。但是内核仍然可以实现三方握手的魔力。客户端接收syn/ack并用最终ack应答,并调用已建立的连接。

    您唯一的选择是,在接受第一个连接后立即关闭侦听套接字。(但这可能会导致其他连接已经可用。)或者您主动接受其他连接并立即关闭它们以通知客户端。