connect & send 在三次握手过程中的有趣问题

一、问题回顾

面试的时候被问到的问题,原问题是:

1:写一下socket网络编程服务端和客户端常用的函数。
2:如果服务端在listen之后没有accept,那客户端的connect会返回吗?为什么?
3:此时调用send发数据会怎么样?

在看下面答案之前,推荐阅读:
深入探索 Linux listen() 函数 backlog 的含义

Socket accept queue is full 但是一个连接需要从SYN->ACCEPT

下面是我对这个问题实验整理的结果:

情况ESTABLISHED 队列没有满SYN_RECV队列没有满SYN_RECV 队列满了
connect返回情况connect 正常返回connect 正常返回connect返回timeout错误
send写数据完全正常写,并且数据会被服务器回复ack确认。之后如果accept,可以read出数据。不能正常发送,会不断触发重传,但是数据不会被确认。这时候的socket是完全disconnect的,send给disconnect的socket写数据,触发SIGPIPE信号,默认杀死本进程。

二、总结

有关connect函数返回错误的情况,常见的有下面三种:

  • 返回TIMEOUT,即SYN_RECV队列都满了,对于客户端发来的三次握手第一次的SYN都没有办法响应,这时候TCP会隔6s24s重发,直到75s,如果还是没有被接受,最后返回TIMEOUT错误。
  • 返回ECONNREFUSED错误,表示服务器主机没有在相应的端口开启监听。
  • 返回EHOSTUNREACHENETUNREACH,表示在某个中间路由节点返回了ICMP错误,这个错误被内核先保存,之后继续按照6s24s重发,直到75s,如果还是没有响应,就返回EHOSTUNREACHENETUNREACH错误。

我那个问题只涉及了TIMEOUT的情况,没有后两种,另外:

connect什么时候正常返回?

其实是客户端收到服务器三次握手第二次返回的SYN+ACK之后,自己进入了ESTABLISHED状态(TCP状态转换图),这时候connect就会正常返回了。

posted on 2017-04-09 10:12  杨博东的博客  阅读(61)  评论(0编辑  收藏  举报

导航