【发布时间】:2011-02-06 13:50:38
【问题描述】:
今天课堂上贴了一个关于套接字编程中的API设计的问题。
为什么listen()和accept()作为不同的函数提供,而不是合并成一个函数?
现在据我所知,listen 将已连接的套接字标记为准备好接受连接,并在传入连接队列上设置最大界限。如果accept和listen合并,这样的队列可以不维护吗?
还是有其他解释?
提前致谢。
【问题讨论】:
标签: sockets network-programming listen
今天课堂上贴了一个关于套接字编程中的API设计的问题。
为什么listen()和accept()作为不同的函数提供,而不是合并成一个函数?
现在据我所知,listen 将已连接的套接字标记为准备好接受连接,并在传入连接队列上设置最大界限。如果accept和listen合并,这样的队列可以不维护吗?
还是有其他解释?
提前致谢。
【问题讨论】:
标签: sockets network-programming listen
listen() 表示“开始监听客户”accept() 的意思是“接受一个客户端,在必要时阻塞直到连接”将这两者分开是有意义的,因为如果它们被合并,那么单个合并的函数就会阻塞。这会导致非阻塞 I/O 程序出现问题。
例如,让我们以一个典型的服务器为例,它既要侦听新的客户端连接,又要监视现有的客户端连接以获取新消息。像这样的服务器通常使用非阻塞 I/O 模型,因此它不会在任何一个特定的套接字上被阻塞。所以它需要一种方法来“开始监听”服务器套接字而不阻塞它。一旦开始监听服务器套接字,服务器套接字就会被添加到通过select()(在某些系统上称为poll())监视的套接字桶中。 select() 调用将指示服务器套接字上何时有客户端挂起。然后程序就可以调用accept(),而不必担心阻塞该套接字。
【讨论】:
在底层,bind 将地址和端口分配给套接字描述符。这意味着该端口现在是为该套接字保留的,因此系统将无法将相同的端口分配给另一个应用程序(存在异常,但我不会在这里详细说明)。这也是每个套接字一次的操作。
然后listen 负责建立可以为给定套接字描述符排队的连接数,并表明您现在愿意接收连接。
另一方面,accept 用于将第一个连接从待处理连接队列中取出,并创建一个新套接字来处理通过它进行的进一步通信。它可能会被多次调用,通常是这样。默认情况下,如果队列中没有连接,则此操作是阻塞的。
现在假设您想使用异步 IO 机制(如 epoll、poll、kqueue、select 等)。如果listen 和accept 是一个单一的API,你将如何表明给定的socket 愿意接收连接?异步机制需要知道您也希望处理此类事件。
由于语义完全不同,将它们分开是有意义的。
【讨论】: