1. TCP建立连接:三次握手,到处都有。需要注意的是ACK确认序列号是SYN携带序列号+1,不是直接相等。基本过程如图所示。
socket程序中调用connect将激发三路握手过程,connect将在成功建立连接或者出错才返回。
(1) 客户端发送SYN以后,6s没有来自服务器的SYN分节响应,则重发SYN,24s后无响应再重发,75s后无响应则返回错误ETIMEOUT。
(2) 对客户端的响应若是RST,则表明服务器端对应端口没有进程等待与之连接,硬错误,返回ECONNREFUSED错误。
(3) 客户发出的SYN在中间路由器发生了“destination unreachable”ICMP错误,客户主机内核保存该信息,按照第一种情况所述时间间隔发送SYN。超时未收到相应,则把保存信息EHOSTUNREACH或ENETUNREACH错误返回给进程。
(4) connect导致套接字从CLOSED状态转换到SYN_SENT,若失败,则此套接字不可用,必须关闭,不能再次调用connect,需要重新调用socket。
服务器端用listen等待建立连接,在accept之前。维护两个队列:未完成连接队列(SYN_RECV)与已完成连接队列(ESTABLISHED)。
(1) 客户SYN到达之后,TCP在未完成连接队列中创建新的一项,然后响应以三路握手的第二个分节:服务器SYN,在队列中保持直到第三个分节到达或者超时(与connect类似的75s)。
(2)服务器端如果一直没有收到ACK第三分节,则会重发服务器SYN分节,套接字保持在未完成队列直到超时。
(3)如果服务器端队列满,收到客户端SYN,会忽略,而不是发送RST,因为情况是暂时的,可能下次就能够有空闲队。RST会让connect立即返回一个错误。
此处是SYN攻击的发生位置。黑客可以伪造大量不存在的IP地址发送SYN建立连接,服务器需要不断回复确认,但是没有响应,继续重发,占用了等待队列,无法为正常连接服务,堵塞网络,其属于典型的DDOS攻击。如果检测到许多随机的半连接IP地址,基本可以判断为SYN攻击(netstat -n -p TCP | grep SYN_RECV)
连接建立成功之后返回,调用accept。
2. TCP断开连接:四次分组交换。确认ACK序列号也是FIN携带序列号+1。
(1) 如果一方已经关闭或异常终止,而另一方不知道,此时TCP连接为半打开。不传输数据,另一方就不会检测到,(此时可以设置TCP的KEEPALIVE选项,来定时检测),如果发送数据,另一方会返回RST分节。
(2) 第四个分节ACK丢失,服务器端(被动关闭)会重发FIN分节。(对照前文,第一个分节发送之后如果没有ack,应该也是超时重发,但此点不确定)
3. TCP建立连接的时候,初始序列号是随机选择的,两次SYN的序列号不固定。
TCP建立连接交换的信息包括:最大分节大小MSS、窗口规模选项、时间戳选项(高速网络需要,避免由失而复现的分组造成数据损坏)。
4. 为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?(慎重对待,不一定正确)
TCP是全双工的,可以在两个方向传输数据,因此需要每个方向单独关闭。一方发送完数据之后就能够用FIN通知对方,一端收到之后,向应用层发送发送通知。
也可如此理解,服务端的LISTEN状态下的SOCKET当收到SYN报文的建连请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可以未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。
5. TIME_WAIT状态的必要性?
TIME_WAIT的持续时间是2*MSL(最长分节寿命,IP数据包在网络中的最长生存时间),一般是1-4分钟之间,存在的两个理由:
(1) 可靠的实现TCP全双工连接的终止。如果四次交换的最后ACK丢失,服务器将重发FIN,客户端需要能够正确处理,发送ACK,如不维护此状态,将发送RST信息,被解释为一个错误。为了可靠结束,必须应对不得不重传最终的ACK。
(2)允许老的重复分节在网络中消逝。如果在相同的端口与IP之间建立了新的连接,原来的连接的包经过路由处理又重新发送过来,可能被认为是原来的包,因此TCP不给TIME_WAIT状态建立新的连接。2MSL可以保证所有老的包消逝。
6.RST产生的三个条件:
(1) SYN到达目的端口,但是服务器没有对应的监听进程;
(2) TCP想取消一个已有连接;
(3) TCP收到一个根本不存在的连接上的分节。
7. 为了避免拥塞,TCP拥塞控制是采用:慢启动、快速重传等机制,避免过长的定时器机制。
慢启动主要表现在发送窗口的大小:开始是2的指数增加,超过临界值(一般最大值一半)就会改变成线性增长(每收到一个ACK就加1)。
收到3个重复ACK包就认为发生了拥塞,会将窗口设为原来的一半。
8. Nagle算法是为了避免网络中存在太多的小包(协议头比例非常大)造成拥塞,可以用TCP_NODELAY选项关闭。