TCP/IP之TCP报文简介

一、传输控制协议

传输控制协议(Transmission Control Protocol,TCP)的最终目的是为数据提供可靠的端到端传输。TCP工作在OSI模型中的第4层。它能够处理数据的顺序和错误恢复,并且最终保证数据能够到达其应到达的目的地。

二、TCP的段结构

 因为TCP是应用于大数据量传输的情况,所以需要将长的数据流分段,TCP的段结构如下图:

源端口

目的端口

序列号

确认号

头长度


标志

窗口

校验和

紧急数据指针

选项(可变长度)

数据





 TCP地址与IP地址不同,IP地址是字节地址,一个节点可以运行多个应用,TCP的地址是节点的某个应用的地址,这种应用在计算机内部是进程。多个进程的数据传输通过不同的端口完成,因此在TCP段结构中,是已端口表示地址的。

 源端口:16比特,源节点进程端口

目的端口:16比特,目标节点端口

序列号:32比特,TCP对字节流中的每个字节都有编号。假设每个数据段包含1000

数据字节,第一个字节的编号为X,则对于字节流中各段的第一个字节的序列号分别为X,X+1000,X+2000

确认号:32比特,为准备接收的字节序号,即意味着该字节序列号前的字节都已正确接收。

头长度:4比特,随可变长度选项的改变而改变,接收方可根据该数据确定TCP的数据位置。

标志:6比特,该字段包含对其他字段的说明或对控制功能的标志。具体的设置如下:

ACK—说明确认字段中的数据有意义。

URG—说明紧急数据指针字段中的数据有意义

FIN—标志最后的TCP数据段,FIN也称为完成

PSH—指出接收方不必等到一定量的数据再向应用提供数据(一般情况是等待一定量再提供),而是立即提供该数据段,PSH也称为

RST—在有异常情况发生时,发送方通知接收方展示终止连接。释放与连接有关的缓冲区,中断TCP传输,RST也称为复位

SYN—在建立初始连接时,允许双方共同确认初始序号,SYN也称为同步

窗口:16比特,通知接收方还可以发送的数据字节数(因为是全双共通信),接收方可以根据该值改变其发送窗口的大小。

校验和:16比特,进行传输层的差错校验,具体算法是将TCP段的内容转换成一系列的16比特的整数,并相加。

紧急数据指针:16比特,当标志字段中的值为URG时,表示有紧急数据,紧急数据位于段的开始,紧急数据指针指向紧挨着紧急数据后的第一个字节,以区分紧急数据和非紧急数据。对于紧急数据接收方必须尽快发送给高层应用。

选项:可变长度,选项一般包含两个内容,一是在通信双方容量相差很大时,必须在初始建立连接时,确定可接收的段的最大尺寸;另一个是在使用高宽带线路传输大型文件时,允许用16比特来代替32比特的窗口字段。需要注意的是,利用填充选项字段,已保证TCP段的头尺寸是4字节的整数倍。

数据:可变大小,用户提供的数据。

三、TCP的三次握手和四次挥手

1、  建立连接

TCP连接的建立采用三次握手协议。三次握手的具体过程是:第一方向另一方发送连接请求段,另一方回应对连接请求的请求段,第一方再发送对对方确认段的确认。这个过程可以用图1-1表示

image.png

1-1中,SYN为请求建立连接的标志,三次握手过程如下:

T1AB发送请求建立连接段,序列号为X

T2B发送应答AX序列号的请求建立连接的段,该应答段的序列号为Y

T3: A发送对B的应答段的应答,应答号为Y+1,表明应答号为Y的段已连接。

至此,连接建立成功,AB分别发送数据段,序列号分别是X+1Y+1,应答号分别是Y+1X+1

2、  连接释放

因为是双工通信,一方的数据段发送完毕要终止连接时,另一方不一定也发送完数据,因此,TCP连接释放采用对称释放方式。

见图1-2FIN为终止标志,释放连接的过程如下:

image.png

l  AT1时刻接收到应用层的终止请求,发送释放连接段。

l  BT2时刻收到A发送的释放连接段,发送应答段,确认已经收到该段,并通知应用层A已经无数据发送,请求释放连接。

l  此后B仍然可以发送数据,但在T3时刻收到无数据传输的通知,向A发送释放连接段。

l  AT4时刻收到B的释放连接段,AB发送应答段,确认已经收到该段,并中断连接

l  T5时刻B收到A的确认,也中断连接。

 四、TCP三次握手数据包

   客户端与服务端通过三次握手建立连接,最后都会通过端口与端口之间的连接。

【示例】A主机的IP地址为:172.20.20.180 ,B主机IP地址为:172.20.20.178,端口:80处于开发状态。通过主机A访问主机B。

image.png

1)第一次握手,主机A向主机B发送连接请求包,标志位SYN(同步序号)置为1,序号SEQ=0。

查看第二2 个数据包的,发现Flags(SYN),并且SYN的值为1。

image.png

其中的:Sequence Number(raw):是wireshark随机生成的序号。Sequence Number:0  表示 该包序号的相对值。

2)第二次握手,为主机B返回的[SYN,ACK]响应包,即:服务端收到客户端发过来的请求报文,由SYN=1知道客户端要建立连接。向客户端发送一个SYN和ACK都置为1的TCP报文,同时设置本机初始序号SEQ=0,将确认序号(ACK)【即为客户端的序号+1】,客户端的序号,上图为SEQ=0,如下图:

image.png

3)第三次握手,客户端收到服务端发来的响应包后,检查确认序号(ACK)是否正确,即第一次发送的序号+1(X+1=1)。以及标志位ACK是否为1,。若正确,服务器再次发送确认包,ACK标志位为1,SYN为0,确认序号(ACK)= 主机B的SEQ+1=0+1=1,发送序号+1=1,客户端收到确认序号与ACK=1 ,则建连成功。

image.png


五、TCP四次挥手数据包

 TCP连接释放的整个过程,见下图:

image.png

首先通过wireshark转包,看一下整体TCP断开连接情况

image.png

为展示效果更佳,写了python的socket的简单demo

服务端的IP:172.20.20.178 端口 12345 ,客户端IP:172.20.20.180

服务端代码:

#!/usr/bin/python

# -*- coding: utf-8 -*-

# 服务端程序

import socket

import time

if __name__ == '__main__':

    # 1.创建socket(套接字)对象

    serv = socket.socket()

    # 2.绑定地址信息

    host = socket.gethostname()

    port = 12345

    serv.bind((host, port))

    # 3.开启监听

    serv.listen(5)  # 最大的等待序列数

    print("Server Port beging,wait connect ...")

    # 4.等待从客户端的连接

    #while 1:

    conn, address = serv.accept()  # 返回socket连接对象和客户端地址address,是个元组结构

    #print("连接地址:%s"%(str(address[0])))

    msg = "Hello"

    conn.send(msg.encode('utf-8'))

    time.sleep(1)

    serv.close()


客户端代码:

#!/usr/bin/python

# -*- coding: utf-8 -*-

# 客户端程序

from socket import *

import time

if __name__ == '__main__':

    client = socket(AF_INET, SOCK_STREAM)

    # 1.创建和服务器的连接

    host = '172.20.20.178'

    port = 12345

    ADDR = (host, port)

    client.connect(ADDR)

    # 接收小于 1024 字节的数据

    msg = client.recv(1024)

    client.close()

    #print (msg.decode('utf-8'))


1)第一次挥手,首先客户端(180地址)给服务端(178地址)发送TCP包,用来关闭客户端到服务端的数据传送。将标志位FIN和ACK置为1,序号为 X=1,确认序号Z=6。(此时客户端进入FIN_WAIT_1状态)

通过查看第19个数据包:

image.png

2)第二次挥手,服务端收到FIN后,回传一个ACK(标志位ACK=1),确认序号为收到的序号加1,即X=X+1=2。序号为收到的确认序号=Z(即为6)。(此时进入CLOSE_WAIT状态)

 通过查看第20的数据包,见下图:

image.png

3)第三次挥手:服务端关闭与客户端的连接,发送一个FIN。将标志位FIN和ACK置为1,序号为Y=1,确认序号为X=2。(此时进入LAST_ACK状态)

通过查看第23个数据包:

image.png


4)第四次挥手:客户端收到服务端发送的FIN后,回传ACK确认(标志位ACK=1),确认序号为收到的序号+1,即Y+1=7,序号为收到的确认序号为X=2。(此时客户端进入TIME_WAIT状态,服务端进入CLOSED状态)

通过查看第24数据包,见下图:

image.png


TCP中的序列号和确认号有什么作用:

序列号,TCP将每个字节的数据进行了编号

序列号的作用:

1、保证可靠性(如当收到的数据少了某个序号的数据时,就能立马知道)

2、保证数据的按序到达

3、提高效率,可实现多次发送,一次确认

4、去除重复数据块

确认号(ACK)的作用:TCP通过确认应答机制实现可靠的数据传输。在TCP的首部字段中有标志位:ACK,通过该标志位 ACK=1 来确认字段有效。

总结:

TCP协议保证数据传输可靠性的方式主要有:

1、校验和

2、序列号

3、确认应答机制

4、重试重传机制

5、连接管理机制

6、流量控制

7、拥塞控制


猜你喜欢

转载自blog.51cto.com/3388803/2661407