"Hello World"
这部分的内容包括连接的正常结束与异常结束。
TCP在关闭连接的时候会发生四步握手。拿上次的图来说,就是简单的把“bye”换成FIN,“ok”换成ACK,大体的情况就是这样,实际上FIN是一个数据包中的标志位,ACK是一个确认序号。
先说正常关闭,正常关闭就是当其中一方(假设是客户)关闭连接时候,就会发送一个FIN给服务器,告诉服务器我要终止连接,然后服务器收到FIN后就发回ACK表示收到,再发送FIN表示,那我也关闭连接,然后客户收到对方的ACK跟FIN后就发回ACK,最后在服务器在收到ACK后就终止连接。
再来就是异常关闭的情况,主要有这么几种情况(我们假设都是在服务器这端出现错误):
1. 进程奔溃
2. 主机奔溃
3. 主机奔溃即刻重启
4. 主机关机
进程奔溃
服务器进程奔溃,可以理解为你强制中止了服务器进程,那么进程就相当于提前进行了资源回收的步骤,那么就会发送FIN给客户,如果客户此刻正阻塞在读写中(比如客户程序在等待你从键盘上输入文本),那么在你写完后,然后TCP依旧会帮你发送,因为FIN只是告诉你我要中止我们之间的连接,并没有告诉我,进程已经关闭了,那么对方收到你的信息后,因为已经没有人再为你服务了(进程已经关闭了),于是对方就发送一个RST给你,就相当于告诉你,我这里根本没有你说的进程来响应你。如果这时候你再往一个接收了RST的套接字写东西,你就会收到系统的“警告”(SIGPIPE信号),然后返回-1,并且设置errno为EPIPE。
主机奔溃
主机奔溃呢就想象成你直接把电源给拔了。那么这时候根本来不及发送任何的信息给客户,包括FIN。则这时候我们往套接字写任何信息,我们都不会收到任何回复,于是这时候客户进程以为是网络繁忙导致丢包,于是它就会隔一段时间重发一次,在一段时间内,他一直重发,如果都没有收到回复,那么它就会终止这次的连接,书上提到的这个时间是9分钟,这是相当长的一段时间,这种情况只会发生在我们往套接字写数据时才能得知,如果我们不进行任何操作我们是不知道的。
主机奔溃再重启
主机在奔溃后及时重启并且重新运行服务进程,那么服务器会收到之前的信息,但是它很迷茫,我明明才刚启动,也没有建立连接,怎么会有数据发送给我?于是他就回复一个RST告诉客户,“你发错人了”。然后客户收到RST后,如果此时正阻塞在读套接字的话,会返回ECONNREST错误。这次我们就讲了关于读写一个收到RST套接字发生的错误了。
主机关机
主机关机的话,系统会通知所有进程做好关闭准备,那么服务器就像客户发送FIN,然后情况跟第一种一样。
关于关闭的事情就讲到这里了。之后就是对之前所讲的内容进行补充了。
领取专属 10元无门槛券
私享最新 技术干货