TCP报文是TCP层传输的数据单元,也叫作报文段。TCP报文结构如下图所示。
Tcp报文 - 图1
下面对报文内容做详细介绍。
(1)端口号:用来标识同一台计算机的不同应用进程。
● 源端口:源端口和IP地址的作用是标识报文的返回地址。
● 目的端口:目的端口指明接收方计算机上的应用程序接口。
TCP报头中的源端口号和目的端口号同IP数据包中的源IP地址和目的IP地址唯一确定一条TCP连接。
(2)序号和确认号:TCP可靠传输的关键部分。序号是本报文段发送的数据组的第一个字节的序号。在TCP传送的流中,每一个字节都有一个序号。例如:一个报文段的序号为300,此报文段数据部分共有100字节,则下一个报文段的序号为400。所以序号确保了TCP传输的有序性。
确认号,即ACK,指明下一个期待收到的字节序号,表明该序号之前的所有数据已经正确无误地收到。确认号只有当ACK标志为1时才有效。比如建立连接时,SYN报文的ACK标志为0。
(3)数据偏移/头部长度:4位。由于头部可能含有可选项内容,TCP报头的长度是不确定的,报头不包含任何任选属性则长度为20字节,4位头部长度属性所能表示的最大值为1111,转化成十进制为15,15×32/8=60,故报头最大长度为60字节。头部长度也叫数据偏移,是因为头部长度实际上指示了数据区在报文段中的起始偏移值。
(4)保留:为将来定义新的用途保留,现在一般设置为0。
(5)标志位:URG、ACK、PSH、RST、SYN、FIN,共6个,每一个标志位都表示一个控制功能,具体含义如下表所示。
Tcp报文 - 图2
(6)窗口:滑动窗口大小,用来告知发送端接收端的缓存大小,以此控制发送端发送数据的速率,从而达到流量控制。窗口大小是一个16位属性,因而窗口大小最大为65535。
(7)校验和:奇偶校验,此校验和针对整个TCP报文段,包括TCP头部和TCP数据,以16位属性进行计算所得。由发送端计算和存储,并由接收端进行验证。
(8)紧急指针:只有当URG标志为1时紧急指针才有效。紧急指针是一个正的偏移量,和顺序号属性中的值相加表示紧急数据最后一个字节的序号。TCP的紧急方式是发送端向另一端发送紧急数据的一种方式。
(9)选项和填充:最常见的可选属性是最长报文大小,又称为MSS(Maximum Segment Size),每个连接方通常都在通信的第一个报文段(为建立连接而设置SYN标志为1的那个段)中指明这个选项,它表示本端所能接收的最大报文段的长度。选项长度不一定是32位的整数倍,所以要加填充位,即在这个属性中加入额外的零,以保证TCP头部长度是32位的整数倍。
(10)数据部分:TCP报文段中的数据部分是可选的。在一个连接建立和一个连接终止时,双方交换的报文段仅有TCP头部。如果一方没有数据要发送,也使用没有任何数据的头部来确认收到的数据。在处理超时的许多情况中,也会发送不带任何数据的报文段。
TCP交互流程
传输连接包括三个阶段:连接建立、数据传送和连接释放。传输连接管理就是对连接建立和连接释放过程的管控,使其能正常运行,以达到这些目的:使通信双方能够确知对方的存在、可以允许通信双方协商一些参数(最大报文段长度、最大窗口大小等)、能够对运输实体资源进行分配(缓存大小等)。TCP连接的建立采用客户端-服务器模式:主动发起连接建立的应用进程叫作客户端,被动等待连接建立的应用进程叫作服务器。接下来,介绍TCP完成数据传输的三次握手和四次挥手的详细过程。
第一次握手:建立连接时,客户端发送SYN包(syn=1)到服务器,并进入SYN_SENT状态,等待服务器确认。
第二次握手:服务器收到SYN包,必须确认客户端的SYN包(ack=x+1),同时自己也发送一个SYN包(syn=1),即SYN+ACK包,此时服务器进入SYN_RECV状态。
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。
至此,TCP连接就建立了,客户端和服务器可以愉快地“玩耍”了。只要通信双方没有一方发出连接释放的请求,连接就将一直保持。如果有一方释放连接,就会发起挥手操作。
第一次挥手:客户端进程发出连接释放报文,并且停止发送数据。释放数据报文头部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN_WAIT_1(终止等待1)状态。TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
第二次挥手:服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务器就进入了CLOSE_WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器方向的连接就被释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接收。这个状态还要持续一段时间,也就是整个CLOSE_WAIT状态持续的时间。
客户端收到服务器的确认请求后,客户端就进入FIN_WAIT_2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接收服务器发送的最后的数据)。
第三次挥手:服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST_ACK(最后确认)状态,等待客户端的确认。
第四次挥手:客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME_WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2×MSL(最长报文段寿命)的时间,当客户端撤销相应的TCB(Transmit Control Block,传输控制模块)后,才进入CLOSED状态。
最后,服务器只要收到了客户端发出的确认,就立即进入CLOSED状态。同样,撤销TCB后,就结束了这次TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。
TCP交互的详细过程如下图所示。
Tcp报文 - 图3

应用层

在日常操作中,用户使用的都是应用程序,应用程序都工作在应用层。互联网是开放的,大家都可以开发自己的应用程序,数据多种多样,必须规定好数据的组织形式。应用层的功能就是规定应用程序的数据格式。
例如:TCP可以为各种各样的程序传递数据,比如SMTP、HTTP、FTP、POP3等,那么,必须有不同的协议规定电子邮件、网页、FTP数据的格式,这些应用程序协议就构成了“应用层”。如下图所示是应用层协议的基本组成结构示意。
Tcp报文 - 图4
用户从应用程序中发送数据是一个对数据封装的过程,而接收数据则是一个解封装的动作。下面简单介绍一下常用的应用层协议。
1.DNS协议
DNS是英文Domain Name System(域名系统)的缩写,用来把便于人们使用的机器名字转换为IP地址。现在顶级域名TLD(Totel Lead Domination)分为三大类:国家顶级域名nTLD、通用顶级域名gTLD和基础结构域名。域名服务器分为四种类型:根域名服务器、顶级域名服务器、本地域名服务器和权限域名服务器。DNS使用TCP和UDP端口53。当前,对于每一级域名长度的限制是63个字符,域名总长度则不能超过253个字符。
2.HTTP
HTTP(HyperText Transfer Protocol,超文本传输协议)是面向事务的应用层协议。它是互联网上能够可靠地交换信息的重要基础。HTTP使用面向连接的TCP作为运输层协议,保证了数据的可靠传输。
3.FTP
FTP(File Transfer Protocol,文件传输协议)是互联网上使用最广泛的文件传送协议。FTP提供交互式的访问,允许客户指明文件类型与格式,并允许文件具有存取权限。FTP基于TCP工作。
4.SMTP
SMTP(Simple Mail Transfer Protocol,简单邮件传输协议)规定了在两个相互通信的SMTP进程之间应如何交换信息。SMTP通信的三个阶段:建立连接、邮件传送和连接释放。
5.POP3
POP3(Post Office Protocol 3,邮件读取协议)通常被用来接收电子邮件。
6.Telnet协议
Telnet协议是一个简单的远程终端协议,也是互联网的正式标准,又称为终端仿真协议。

小结

总结一下OSI七层模型,它为开放互联信息系统提供了一种结构框架。建立七层模型的主要目的是解决异种网络互联时所遇到的兼容性问题。它的最大优点是将服务、接口和协议这三个概念明确地区分开来:服务说明某一层为上一层提供一些什么功能,接口说明上一层如何使用下一层的服务,而协议涉及如何实现本层的服务;这样各层之间具有很强的独立性,互联网络中各实体采用什么样的协议是没有限制的,只要向上提供相同的服务并且不改变相邻层的接口就可以。其详细结构如下图所示。
Tcp报文 - 图5

网络通信实现原理

要想实现网络通信,每台主机需具备四要素:本机的IP地址、子网掩码、网关的IP地址和DNS的IP地址。
获取这四要素有两种方式:一是静态获取,即手动配置;二是动态获取,即通过DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)获取。
下图是网络通信的数据结构示意图。
Tcp报文 - 图6
我们来详细分析一下网络通信的交互过程。
(1)最前面的“以太网头部”,设置发出方(本机)的MAC地址和接收方(DHCP服务器)的MAC地址。前者就是本机网卡的MAC地址,后者这时不知道,就填入一个广播地址:FF-FF-FF-FF-FF-FF。
(2)后面的“IP头部”,设置发出方的IP地址和接收方的IP地址。这时,对于这两者,本机都不知道。于是,发出方的IP地址就设为0.0.0.0,接收方的IP地址设为255.255.255.255。
(3)最后的“UDP头部”,设置发出方的端口和接收方的端口。这一部分是DHCP规定好的,发出方是68端口,接收方是67端口。
这个数据包构造完成后,就可以发出了。以太网是广播发送的,同一个子网的每台计算机都收到了这个数据包。因为接收方的MAC地址是FF-FF-FF-FF-FF-FF,看不出是发给谁的,所以每台收到这个数据包的计算机,还必须分析这个数据包的IP地址,才能确定是不是发给自己的。看到发出方IP地址是0.0.0.0,接收方IP地址是255.255.255.255,于是DHCP服务器知道“这个数据包是发给我的”,而其他计算机就可以丢弃这个数据包。
接下来,DHCP服务器读出这个数据包的数据内容,分配好IP地址,发送回去一个“DHCP响应”数据包。这个响应包的结构也是类似的,以太网头部的MAC地址是双方的网卡地址,IP头部的IP地址是DHCP服务器的IP地址(发出方)和255.255.255.255(接收方),UDP头部的端口是67(发出方)和68(接收方),分配给请求端的IP地址和本网络的具体参数则包含在Data部分。
新加入的计算机收到这个响应包,于是就知道了自己的IP地址、子网掩码、网关地址、DNS服务器等参数。

向浏览器输入URL后发生了什么

当在浏览器地址栏中输入网址后,浏览器是怎么把最终的页面呈现出来的呢?这个过程大致可以分为两个部分:网络通信和页面渲染。下面详细分析完整的通信过程。
第一步,本机设置以下信息。
Tcp报文 - 图7
第二步,打开浏览器,想要访问咕泡官网,在地址栏中输入网址www.gupaoedu.com。
第三步,通过访问DNS域名系统服务器(基于UDP)获得IP地址。
下图完整地说明了一次网络请求如何获取目标服务器IP地址的全过程。
Tcp报文 - 图8
图中13台国际DNS根服务器IP地址具体如下。
Tcp报文 - 图9
Tcp报文 - 图10
通过域名寻找到目标机器所在位置。下面简单科普一下域名知识,域名有顶级域名和二级域名。顶级域名如.com、.net、.org、.cn等属于国际顶级域名。根据目前的国际互联网域名体系,国际顶级域名分为两类:类别顶级域名(gTLD)和地理顶级域名(ccTLD)。类别顶级域名是以“com”“net”“org”“biz”“info”等结尾的域名,均由国外公司负责管理。地理顶级域名是以国家或地区代码为结尾的域名,如“cn”代表中国,“uk”代表英国。地理顶级域名一般由各个国家或地区负责管理。在不同的地域还会使用二级域名,二级域名是以顶级域名为基础的地理域名,例如中国的二级域有.com.cn、.net.cn、.org.cn、.gd.cn等。
在实际的网站应用中,通常会使用子域名。比如父域名是abc.com,子域名就是www.abc.com或者.abc.com。一般来说,子域名是域名的一条记录,比如gupaoedu.com是一个域名,www.gupaoedu.com是其中比较常用的记录,一般默认类似.gupaoedu.com的域名全部被称作gupaoedu.com的子域名。
第四步,向目标机器发起HTTP请求,获得如下格式的数据内容。
Tcp报文 - 图11
我们假定这个部分的长度为4960字节,它会被嵌在TCP数据包中。
第五步,TCP。TCP数据包需要设置端口,接收方(咕泡官网)的HTTP端口默认是80,发送方(本机)的端口是一个随机生成的1024~65535之间的整数,假定为51775。TCP数据包的头部长度为20字节,加上嵌入HTTP的数据包,总长度变为4980字节。
第六步,IP。TCP数据包再嵌入IP数据包。IP数据包需要设置双方的IP地址,这是已知的。IP数据包的头部长度为20字节,加上嵌入的TCP数据包,总长度变为5000字节。
第七步,以太网协议。IP数据包嵌入以太网数据包。以太网数据包需要设置双方的MAC地址,发送方为本机的网卡MAC地址,接收方为网关192.168.1.1的MAC地址(通过ARP得到)。以太网数据包的数据部分最大长度为1500字节,而现在的IP数据包长度为5000字节。因此,IP数据包必须分割成四个包。因为每个包都有自己的IP头部(20字节),所以四个包的长度分别为1500字节、1500字节、1500字节、560字节。如下图所示是以太网数据包示意图。
Tcp报文 - 图12
第八步,服务器响应。经过多个网关的转发,咕泡官网的服务器收到了这四个以太网数据包。
根据IP头部的序号,咕泡官网将四个包拼起来,取出完整的TCP数据包,然后读出里面的“HTTP请求”,接着做出“HTTP响应”,再用TCP发回来。本机收到HTTP响应以后,就可以将网页显示出来,完成一次网络通信。