Linux connect() 是否阻止 TCP 套接字?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8258107/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Does connect() block for TCP socket?
提问by kai
Hi I am reading TLPI (The Linux Programming Interface), I have a question about connect().
嗨,我正在阅读 TLPI(Linux 编程接口),我有一个关于 connect() 的问题。
As I understand, connect() will immediately return if the pending connection numbers of listen() doesn't reach "backlog". And it will blocks otherwise. (according to figure 56-2)
据我了解,如果 listen() 的挂起连接数未达到“积压”,connect() 将立即返回。否则它会阻塞。(根据图56-2)
But for TCP socket, it will always block until accept() on server side is called (according to figure 61-5).
但是对于 TCP 套接字,它会一直阻塞,直到调用服务器端的 accept()(根据图 61-5)。
Am I correct? Because I saw that in the example code (p.1265), it calls listen() to listen to a specific port and then calls connect() to that port BEFORE calling accept().
我对么?因为我在示例代码 (p.1265) 中看到了这一点,它调用 listen() 来侦听特定端口,然后在调用 accept() 之前调用 connect() 到该端口。
So connect() blocks forever in this case, doesn't it?
所以在这种情况下 connect() 会永远阻塞,不是吗?
Thanks!!
谢谢!!
采纳答案by nos
There's hardly any "immediately" regarding networking, stuff can be lost on the way, and an operation that should be performed immediately in theory might not do so in practice, and in any case there's the end to end transmission time.
网络上几乎没有什么“立即”,东西可能会在途中丢失,理论上应该立即执行的操作实际上可能不会这样做,无论如何都有端到端的传输时间。
However
然而
connect() on a TCP socket is a blocking operation unless the socket descriptor is put into non-blocking mode.
The OS takes care of the TCP handshake, when the handshake is finished, connect() returns. (that is, connect() does not block until the other end calls accept())
A successful TCP handshake will be queued to the server application, and can be accept()'ed any time later.
除非将套接字描述符置于非阻塞模式,否则 TCP 套接字上的 connect() 是阻塞操作。
操作系统负责 TCP 握手,握手完成后,connect() 返回。(即connect()不会阻塞,直到另一端调用accept())
成功的 TCP 握手将排队到服务器应用程序,并且可以在以后任何时间接受()。
回答by Basile Starynkevitch
回答by blaze
connect() blocks until finishing TCP 3-way handshake. Handshake on listening side is handled by TCP/IP stack in kernel and finished without notifying user process. Only after handshake is completed (and initiator can return from connect() call already), accept() in user process can pick up new socket and return. No waiting accept() needed for completing handshake.
connect() 阻塞直到完成 TCP 3 次握手。侦听端的握手由内核中的 TCP/IP 堆栈处理,并在不通知用户进程的情况下完成。只有在握手完成后(并且发起者已经可以从 connect() 调用返回),用户进程中的 accept() 才能拿起新的套接字并返回。无需等待 accept() 即可完成握手。
The reason is simple: if you have single threaded process listening for connections and require waiting accept() for establishing connections, you can't respond to TCP SYN's while processing another request. TCP stack on initating side will retransmit, but on moderately loaded server chances are high this retransmitted packet still will arrive while no accept() pending and will be dropped again, resulting in ugly delays and connection timeouts.
原因很简单:如果您有单线程进程侦听连接并需要等待 accept() 来建立连接,则在处理另一个请求时无法响应 TCP SYN。发起端的 TCP 堆栈将重新传输,但在中等负载的服务器上,此重新传输的数据包仍然会到达,而没有 accept() 挂起并再次被丢弃,从而导致丑陋的延迟和连接超时。