1.包首部
1)源端和目的端的端口号客户IP地址、客户端口号、服务器IP地址和服务器端口号的四元组)可唯一确定互联网络中每个TCP连接的双方。
2)序号用来标识从TCP发端向TCP收端发送的数据字节流,它表示在这个报文段中的的第一个数据字节。如果将字节流看作在两个应用程序间的单向流动,则TCP用序号对每个字节进行计数。序号是32bit的无符号数,序号到达232-1后又从0开始。
当建立一个新的连接时(或断开连接),序号字段包含由这个主机选择的该连接的初始序号ISN(InitialSequenceNumber)。ISN随时间而变化,因此每个连接都将有不同的ISN。这样做,一方面是为了防止连接失效后SOCKET被重用使得以前残留的包被错误的接受;另一方面是为了防止黑客轻易的知道序列号之后制造tcp序列号攻击。
3)既然每个传输的字节都被计数,确认序号包含发送确认的一端所期望收到的下一个序号。因此,确认序号应当是上次已成功收到数据字节序号加1。只有ACK标志(下面介绍)为1时确认序号字段才有效。
发送ACK无需任何代价,因为32bit的确认序号字段和ACK标志一样,总是TCP首部的一部分。因此,我们看到一旦一个连接建立起来,这个字段总是被设置,ACK标志也总是被设置为1。
4)首部长度给出首部中32bit字的数目。需要这个值是因为任选字段的长度是可变的。这个字段占4bit,因此TCP最多有60字节的首部。然而,没有任选字段,正常的长度是20字节。
5)6个标志比特。它们中的多个可同时被设置为1。
URG紧急指针(urgentpointer)有效
ACK确认序号有效。acknowledge
PSH接收方应该尽快将这个报文段交给应用层。push
RST重建连接。reset
SYN同步序号用来发起一个连接。synchronization
FIN发端完成发送任务。finish
6)TCP的流量控制由连接的每一端通过声明的窗口大小来提供。窗口大小为字节数,起始于确认序号字段指明的值,这个值是接收端正期望接收的字节。窗口大小是一个16bit字段,因而窗口大小最大为65535字节。
7)检验和覆盖了整个的TCP报文段:TCP首部和TCP数据。这是一个强制性的字段,一定是由发端计算和存储,并由收端进行验证。TCP检验和的计算和UDP检验和的计算相似。
8)只有当URG标志置1时紧急指针才有效。紧急指针是一个正的偏移量,和序号字段中的值相加表示紧急数据最后一个字节的序号。TCP的紧急方式是发送端向另一端发送紧急数据的一种方式。
9)最常见的可选字段是最长报文大小,又称为MSS(MaximumSegmentSize)。每个连接方通常都在通信的第一个报文段(为建立连接而设置SYN标志的那个段)中指明这个选项。它指明本端所能接收的最大长度的报文段。
2.三次握手
1)请求端(通常称为客户)发送一个 SYN 报文段( SYN 为 1 )指明客户打算连接的服务器的端口,以及初始顺序号( ISN )。
2)服务器发回包含服务器的初始顺序号的 SYN 报文段( SYN 为 1 )作为应答(还有服务器顺序号)。同时,将确认号设置为客户的 ISN 加 1 以对客户的 SYN 报文段进行确认( ACK 也为 1 )。
3)客户必须将确认号设置为服务器的 ISN 加 1 以对服务器的 SYN 报文段进行确认( ACK 为 1 ),该报文通知目的主机双方已完成连接建立。
3.关闭连接
因为 TCP 的半关闭( half-close ),所以才要4次握手才能关闭TCP(图上有错,是4次)。由于一个 TCP 连接是全双工(即数据在两个方向上能同时传递),因此每个方向必须单独地进行关闭。关闭的原则就是当一方完成它的数据发送任务后就能发送一个 FIN 来终止这个方向连接。当一端收到一个 FIN ,它必须通知应用层另一端已经终止了那个方向的数据传送。发送 FIN 通常是应用层进行关闭的结果。
从一方的 TCP 来说,连接的关闭有三种情况:
• 本方启动关闭
收到本方应用进程的关闭命令后, TCP 在发送完尚未处理的报文段后,发 FIN = 1 的报文段给对方,且 TCP 不再受理本方应用进程的数据发送。在 FIN 以前发送的数据字节,包括 FIN ,都需要对方确认,否则要重传。注意 FIN 也占一个顺序号。一旦收到对方对 FIN 的确认以及对方的 FIN 报文段,本方 TCP 就对该 FIN 进行确认,在等待一段时间,然后关闭连接。等待是为了防止本方的确认报文丢失,避免对方的重传报文干扰新的连接。
• 对方启动关闭
当 TCP 收到对方发来的 FIN 报文时,1.发 ACK 确认此 FIN 报文,并通知应用进程连接正在关闭。应用进程将以关闭命令响应。 2.TCP 在发送完尚未处理的报文段后,发一个 FIN 报文给对方 TCP ,然后等待对方对 FIN 的确认,收到确认后关闭连接。若对方的确认未及时到达,在等待一段时间后也关闭连接。
• 双方同时启动关闭
连接双方的应用进程同时发关闭命令,则双方 TCP 在发送完尚未处理的报文段后,发送 FIN 报文。各方 TCP 在 FIN 前所发报文都得到确认后,发 ACK 确认它收到的 FIN 。各方在收到对方对 FIN 的确认后,同样等待一段时间再关闭连接。这称之为同时关闭( simultaneous close )。
当关闭连接时,read函数会返回-1!。
4.TCP状态机
表 3-2 TCP 状态表
状 态 |
描 述 |
CLOSED |
关闭状态,没有连接活动或正在进行 |
LISTEN |
监听状态,服务器正在等待连接进入 |
SYN RCVD |
收到一个连接请求,尚未确认 |
SYN SENT |
已经发出连接请求,等待确认 |
ESTABLISHED |
连接建立,正常数据传输状态 |
FIN WAIT 1 |
(主动关闭)已经发送关闭请求,等待确认 |
FIN WAIT 2 |
(主动关闭)收到对方关闭确认,等待对方关闭请求 |
TIMED WAIT |
完成双向关闭,等待所有分组死掉 |
CLOSING |
双方同时尝试关闭,等待对方确认 |
CLOSE WAIT |
(被动关闭)收到对方关闭请求,已经确认 |
LAST ACK |
(被动关闭)等待最后一个关闭确认,并等待所有分组死掉 |
5.坚持定时器
如果一个确认丢失了,则双方就有可能因为等待对方而使连接终止:接收方等待接收数据(因为它已经向发送方通告了一个非 0的窗口,但此通告也许丢失),而发送方在等待允许它继续发送数据的窗口更新。为防止这种死锁情况的发生,发送方使用一个坚持定时器 (persist timer)来周期性地向接收方查询,以便发现窗口是否已增大。这些从发送方发出的报文段称为窗口探查 (window probe)。
当TCP服务器收到了客户端的0滑动窗口报文的时候,就启动一个定时器来计时,并在定时器溢出的时候向向客户端查询窗口,是否已经增大,如果得到非零的窗口就重新开始发送数据,如果得到0窗口就再开一个新的定时器准备下一次查询。
6.长连接与短连接和保活定时器
长连接就是Client方与Server方先建立通讯连接,连接建立后不断开。
短连接就是Client方与Server每进行一次报文收发交易时才进行通讯连接,交易完毕后立即断开连接。
保活功能主要为服务器应用提供,服务器应用希望知道客户主机是否崩溃,从而可以代表客户使用资源。如果客户已经消失,使得服务器上保留一个半开放的连接,而服务器又在等待来自客户端的数据,则服务器将应远等待客户端的数据,保活功能就是试图在服务器端检测到这种半开放的连接。
eg:如果一个给定的连接在两小时内没有任何的动作,则服务器就向客户发一个探测报文段,来查看客户有没有ack。
长连接:
Keep-Alive模式,http 1.1中默认启用Keep-Alive,如果加入"Connection: close ",才关闭。目前大部分浏览器都是用http1.1协议,也就是说默认都会发起Keep-Alive的连接请求了,所以是否能完成一个完整的Keep- Alive连接就看服务器设置情况。
如何判断消息内容/长度的大小?
7.java TCP
//创建Socket 客户端对象
Socket s = new Socket("127.0.0.1",6666);
//创建ServerSocket 服务器端对象。。
ServerSocket ss = new ServerSocket(6666);
//监听服务器连接
s = ss.accept()();
参考(转):TCP/IP详解 stevens