是否为TCP套接字连接()块?

是否为TCP套接字连接()块?

问题描述:

您好我正在阅读TLPI(Linux编程接口),我有一个关于connect()的问题。是否为TCP套接字连接()块?

据我所知,如果listen()的未决连接数没有达到“backlog”,connect()会立即返回。 否则会阻塞。 (根据图56-2)

但是对于TCP套接字,它将一直阻塞,直到调用服务器端的accept()为止(根据图61-5)。

我正确吗? 因为我在示例代码(p.1265)中看到,它调用listen()来监听特定端口,然后在调用accept()之前调用connect()到该端口。

因此connect()在这种情况下永远阻塞,不是吗?

谢谢!

+0

如果这就是图56-2所显示的,那就错了。 – EJP

关于网络几乎没有任何“立即”的东西可以在途中丢失,而理论上应立即执行的操作在实践中可能不会这样做,并且在任何情况下都存在端到端传输时间。

然而

  • 上的TCP套接字连接

    ()是一个阻塞操作,除非套接字描述符放入非阻塞模式。

  • 操作系统负责TCP握手,当握手完成时,connect()返回。 (即, connect()不会阻塞,直到另一端调用accept())

  • 成功的TCP握手将排队等待服务器应用程序,并且可以在随后的accept()''编辑。

+0

只是想补充一下'connect'只是等待握手而不是服务器调用'accept',这是因为两个原因:第一个是来自客户端的他在握手后连接;第二个是因为可以在握手之间传递任意时间,并且在服务器调用“accept”之前,这确实是永远的。 –

+1

即使没有答案的其余部分,“几乎没有任何'立即'”单独保证+1。即使在非阻塞模式下,这对于很多操作也是如此。有时甚至可能会很快,甚至对于那些你不会期望的事情。 – Damon

+0

@JoachimPileborg @nos如果'connect()'在服务器调用accept()之前返回,如果客户端在服务器调用accept()之前尝试'send(),会发生什么? – Flash

connect默认情况下是阻止呼叫,但您可以通过传递socketSOCK_NONBLOCK标志使其不阻塞。

+4

或者更常见的是,使用fcntl的“传统”BSD套接字函数和O_NONBLOCK。 SOCK_NONBLOCK是Linux专用的。 – MarkR

connect()阻塞,直到完成TCP 3次握手。在监听端的握手由内核中的TCP/IP协议栈处理,并在没有通知用户进程的情况下完成。只有在握手完成后(并且发起者可以从connect()调用已经返回),accept()在用户进程中可以拾取新的套接字并返回。没有等待接受()需要完成握手。

原因很简单:如果您有单线程进程监听连接,并且需要等待accept()来建立连接,则在处理另一个请求时无法对TCP SYN进行响应。初始端的TCP堆栈将重新发送,但是在适度加载的服务器上机率很高,这个重新发送的数据包仍然会到达,而没有accept()挂起并且会再次丢弃,导致丑陋的延迟和连接超时。