【问题标题】:Socket programming - API doubtSocket编程——API疑问
【发布时间】:2011-02-06 13:50:38
【问题描述】:

今天课堂上贴了一个关于套接字编程中的API设计的问题。

为什么listen()和accept()作为不同的函数提供,而不是合并成一个函数?

现在据我所知,listen 将已连接的套接字标记为准备好接受连接,并在传入连接队列上设置最大界限。如果accept和listen合并,这样的队列可以不维护吗?

还是有其他解释?

提前致谢。

【问题讨论】:

    标签: sockets network-programming listen


    【解决方案1】:
    • listen() 表示“开始监听客户”
    • accept() 的意思是“接受一个客户端,在必要时阻塞直到连接”

    将这两者分开是有意义的,因为如果它们被合并,那么单个合并的函数就会阻塞。这会导致非阻塞 I/O 程序出现问题。

    例如,让我们以一个典型的服务器为例,它既要侦听新的客户端连接,又要监视现有的客户端连接以获取新消息。像这样的服务器通常使用非阻塞 I/O 模型,因此它不会在任何一个特定的套接字上被阻塞。所以它需要一种方法来“开始监听”服务器套接字而不阻塞它。一旦开始监听服务器套接字,服务器套接字就会被添加到通过select()(在某些系统上称为poll())监视的套接字桶中。 select() 调用将指示服务器套接字上何时有客户端挂起。然后程序就可以调用accept(),而不必担心阻塞该套接字。

    【讨论】:

    • 哦,我也猜到了。我认为一个人不能同时保持许多连接。谢谢。
    • @ryan 很高兴能够提供帮助
    【解决方案2】:

    listen(2) 使给定的 TCP 套接字成为服务器套接字,即创建一个队列以接受来自客户端的连接请求。 绑定的只有监听端端口和可能的 IP 地址(因此您需要在listen(2) 之前调用bind(2))。 accept(2) 然后实际上从该队列中获取此类连接请求并将其转换为 已连接的套接字(双向通信所需的四个部分 - 源 IP 地址、源端口号、目标 IP 地址和目标端口号 - 已分配)。 listen(2) 只被调用一次,而accept(2) 通常被调用多次。

    【讨论】:

      【解决方案3】:

      在底层,bind 将地址和端口分配给套接字描述符。这意味着该端口现在是为该套接字保留的,因此系统将无法将相同的端口分配给另一个应用程序(存在异常,但我不会在这里详细说明)。这也是每个套接字一次的操作。

      然后listen 负责建立可以为给定套接字描述符排队的连接数,并表明您现在愿意接收连接。

      另一方面,accept 用于将第一个连接从待处理连接队列中取出,并创建一个新套接字来处理通过它进行的进一步通信。它可能会被多次调用,通常是这样。默认情况下,如果队列中没有连接,则此操作是阻塞的。

      现在假设您想使用异步 IO 机制(如 epoll、poll、kqueue、select 等)。如果listen 和accept 是一个单一的API,你将如何表明给定的socket 愿意接收连接?异步机制需要知道您也希望处理此类事件。

      由于语义完全不同,将它们分开是有意义的。

      【讨论】:

        猜你喜欢
        • 2012-03-22
        • 1970-01-01
        • 2017-01-29
        • 1970-01-01
        • 2012-02-11
        • 1970-01-01
        • 2011-09-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多