计算机网络-tcp简介
TCP报文段的首部格式
ACK=1表示该报文段包含确认序号(ack),只有在tcp三次握手的首次请求中ACK=0;
SYN=1表示该报文段用于同步序号,只有在tcp三次握手的前两次握手中SYN=1(两次握手之后,双方就会各持有一对序号,一个是自己的,另一个是对端的);
FIN=1表示该报文段为终止报文段,即向对端表示我不再发送数据给你了(但我还可以接收你发送的数据);
窗口字段表示当前可接收的最大字节数,是动态变化的;
确认号ack表示已收到对端到ack-1为止的所有数据;
客户端状态的变迁:关闭->同步已发送->连接已建立;
服务端状态的变迁:关闭->监听->同步已接受->连接已建立;
通常都是客户端主动请求
客户端状态的变迁:连接已建立->终止等待-1->终止等待-2->时间等待->关闭
服务端状态的变迁:连接已建立->关闭等待->最后确认->关闭
以java socket编程为例,serverSocket监听8181,clientSocket绑定8282,clientSocket.close后双方tcp的状态如下图(可通过netstat -ano查看),serverSocket处于CLOSE_WAIT,clientSocket处于FIN_WAIT_2。此时,对于java Socket来说,clientSocket已不能再发送数据(应用程序将clientSocket标记为closed,os Socket底层也关闭了发送通道),serverSocket读取数据只会读到-1,虽然可以发送数据,但clientSocket已经无法再接收了(因为被标记为closed,可能其他语言此时还可以接收数据)。也就是说,对于java而言,一端关闭了,另一端就会只有关闭的份了,不能再传输数据了。
当serverSocket.close后,serverSocket持有的临时端口被关闭,只剩下处于TIME_WAIT状态的clientSocket的8282端口,经测试TIME_WAIT状态会持续很长时间,所以通常建议client端主动进行关闭,如果server端主动关闭,会存在大量的端口处于TIME_WAIT状态,剩余可用端口就变少了。
(如果长时间维持clientSocket关闭、serverSocket开启的状态,即client为FIN_WAIT_2,server为CLOSE_WAIT,最后二者都会关闭,这是什么原因呢?)
CLOSE_WAIT、FIN_WAIT_2、TIME_WAIT这三个状态较容易捕捉,其他状态都是瞬间状态,不容易捕捉到。
参考:http://network.51cto.com/art/201411/456783.htm