Socket编程 - listen()和accept()有什么区别?

48
我一直在阅读这个教程学习socket编程。看起来listen()accept()系统调用都做同样的事情,即阻塞并等待客户端连接到使用socket()系统调用创建的套接字。为什么需要两个单独的步骤呢?为什么不只使用一个系统调用?
顺便说一下,我已经谷歌了这个问题并找到了类似的问题,但没有一个令人满意的答案。例如,其中一个回答说accept()创建套接字,这是没有意义的,因为我知道套接字是由socket()创建的。
4个回答

56

listen()函数主要在内部套接字结构中设置一个标志,将套接字标记为被动监听套接字,在这种套接字上可以调用accept函数。它打开绑定的端口,以便套接字可以开始接收客户端连接。

accept()函数要求监听套接字接受下一个传入的连接,并返回该连接的套接字描述符。因此从某种意义上说,accept()确实会创建一个套接字,但不是用于listen()等待传入连接的套接字。


好的,我现在觉得我有点明白了。 - Zen Hacker

35

这都是历史设置的一部分。 listen 为下一个 accept 调用准备套接字。同时,它还允许您设置队列(backlog) - 这是系统将要接受的连接数,并等待您的程序真正接受它们。在队列满之后到达的所有内容都将被系统立即拒绝。 listen 不会阻塞,而 accept 会阻塞(除非套接字处于非阻塞模式),直到下一个连接到来。显然,这不一定要是两个单独的函数 - 可以想象 accept() 函数可以完成 listen 的所有操作。


11
上面的两个答案清楚地说明了accept和listen之间的区别。回答你的另一个问题 - 为什么我们需要两个单独的函数?
一个用例是,例如,如果您只想测试端口是否仍然可用/可访问,您可以通过仅侦听端口然后关闭它而不接受任何连接来实现。
例如,https://github.com/coolaj86/golang-test-port 使用listen调用来测试端口的可用性。

1

listen()使用一个backlog参数,它指定了排队连接的最大数量,应该至少为0。随着服务器同时接收到许多连接请求,它的值会增加。

accept()等待传入的连接。当客户端连接时,它返回一个表示连接的新套接字对象。

另一个必须注意的事情是,accept()创建一个新的套接字对象,将用于与客户端通信。它不同于服务器用于接受新连接的监听套接字。

每个应用程序和TCP/IP套接字接口之间的连接允许的最大套接字数为65535。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接