tcp协议和报文传输服务器,详解TCP协议,带你三分钟全面理解

TCP(Transmission Control Protocol):

面向连接的,可靠的,基于字节流的传输层通信协议

特点:

基于连接的:数据传输之前需要建立连接

全双工的:可以双向传输

字节流:不限制数据大小,打包成报文段,保证有序接收,重复报文自动丢弃

流量缓冲:解决双方处理能力的不匹配

可靠的传输服务:保证可达,丢包时通过重发机制实现可靠性

拥塞控制:防止网络出现恶性拥塞

TCP报文格式:

54774b7c858ed82f4c189df7682ec1e2.png

Options可选参数上面的字段是必选的字段;

Source port源端口发送端随机生成,Dest port目的端口为服务器的端口;

Sequence number序列号,Acknowledgment number应答号码,这两个编号用来保证数据的可靠性传输;

Header length头长度,Unused保留字段,竖着的是报文类型标识,如SYN同步序列号说明是建立连接的报文,ACK响应的报文可以是确认握手的报文已经到达或者传送数据的时候确认数据已经收到,FIN关闭连接的报文;

Receive window是当前服务器可以接收数据的窗口大小的一个值,会受到网络的影响,大小不是稳定的值;

Urgent data pointer紧急数据指针,如果报文类型为URG,说明这个数据需要应用程序优先处理,紧急数据指针指向一个内存空间,紧急处理一下;

Data真实的业务数据,发送HTTP报文的时候,Data里面放的就是HTTP协议的数据;

TCP连接管理

TCP连接:四元组[源地址,源端口,目的地址,目的端口]

确立连接:TCP三次握手a.同步通信双方初始序列号(ISN,initial sequence number)b.协商TCP通信参数(MSS,窗口信息,指定校验和算法)

如何进行握手?

c1f5dd2a34184fc7b418f9546668957a.png

客户端拿到IP地址后,开始三次握手:

刚开始服务器端首先会进入Listen的状态,比如Nginx监听某一个端口80,客户端发送一个请求之前会先创建一个数据结构create tcb(Transmission Control Block),存储发送的端口号以及其他信息,客户端向服务器端发送SYN同步序列号报文后,客户端进入SYN-SENT状态,当服务器端收到SYN报文的时候,进入SYN-RECEIVED状态,服务器端在本地创建数据结构create tcb(Transmission Control Block),存储连接信息,回送一个ACK的确认报文,表示同步序列号的报文我收到了,并且同时会发送一个SYN的报文给客户端,客户端在收到服务器端回送的ACK确认报文后,就进入了ESTABLISHED状态,说明客户端连接已经建立了,客户端在收到服务器端发送的SYN报文后,会向服务器端发送一个ACK确认报文,通知服务器端,我已经收到SYN报文了,当服务器端收到ACK报文后,进入ESTABLISHED状态,建立连接。

客户端和服务器端发送SYN报文时会携带随机生成的seq序列号,发送ACK报文时,会携带对应的SYN报文携带的序列号加一的序列号,表示确认的是这个SYN。

下面做一个实验说明一下三次握手:

在本地安装一个Nginx服务器,部署一个静态页面

7f5d4fb417c5d6323daec3f6b75b75be.png

访问静态页面,看一下客户端与服务端交互之前的三次握手,抓一下和Nginx服务器通信之前的报文,怎么进行抓包呢?我们可以使用tcpdump -help 来查看一下

00ef407a9a1eb0f750e92ef57730fa03.png

使用tcpdump可以指定对应的网卡,因为是要从本地发送请求到服务器上面,所以它们要在同一个网段,选择与本机同一网段的网卡

ipconfig 查看本机的网段

ifconfig 查看与本机同一网段的网卡

最后执行 tcpdump -i 网卡 -S(相对序列号转化为绝对序列号)-c 3 port 80 (指定监听某个端口)

看三次握手的话 加一个 -c 3 代表抓到三个报文后就停止,回车进入监听状态

本机装了一个nc的网络工具 发送tcp三次握手的请求

d7135e2076b3f4de366a50f7e4e27561.png

输入服务器的地址和端口,回车,这个时候就建立了三次握手

监听那边抓到三次报文后立刻结束

23456aa64702c2c10bba2fae5a447f54.png

第一条报文可以看到是由我们主机向服务器发送的报文,Flags 代表报文的类型 S就是SYN .就是ACK seq 随机序列号 win 主机窗口大小 options tcp用的参数

第二条报文可以看到是服务器向主机发送的报文 可提的就是ack 后面的序列号就是 第一条报文序列号加一

第三条是主机向服务器发送的确认报文

三次握手时内核的动作:

c54147a7c83cb94380d37a7d09359a67.png

当SYN报文到达后,会进入内核的SYN队列,进入SYN_RECEIVED状态,并且立刻发送SYN/ACK报文到客户端,接下来服务端等待客户端回传一个确认报文,当收到确认报文,内核会把SYN队列中的报文出队,入队到ACCEPT队列中,应用程序监听到ACCEPT内有可用连接,就会到队列中去,建立连接,服务端状态变为ESTABLISHED

如何查看tcp连接:

netstat -tpn -c 1

-t 查看当前tcp连接的状态

-p 显示对应的进程

-n 数字形式查看IP和port

-c 任务执行时间间隔 1 代表每秒一次

babe19dcdf54c5c5a9859ca505b9b719.png

现在State是ESTABLISHED,我们在创建一个TCP连接,看一下状态

telnet 192.168.109.200 80

执行命令如果出现telnet不是内部或外部命令时,代表着计算机没有开启telnet服务,打开控制面板,找到启用或关闭Windows功能,勾选Telnet Client,点击确定进行安装

826a0109ab6eae65a4bd56cc881fccc9.png

连接成功

如果把80端口的连接关闭会发生什么呢?

4a75f1e38f87399354a6412f931d12f6.png

State变为TIME_WAIT,刚才说握手的时候是没有TIME_WAIT状态的,那这个状态是怎么出来的呢,这里就要看一下断开连接的时候的四次挥手了

大家都知道,建立连接的时候会消耗很多系统资源,所以连接不用的话,要去把它关掉,避免浪费系统资源,关闭连接是双向的全双工的一个协议,客户端可以直接关,服务端也可以直接关

现在我们把主动关闭的叫客户端,被动关闭的叫服务端,带大家来看一下四次挥手的过程

四次挥手:

f42ee33dcef9b5e8a9236554dff4b5d6.png

客户端执行CLOSE命令,发送一个FIN报文到服务器端,客户端变为FIN_WAIT_1状态,服务器端收到报文之后,立刻回传一个响应报文,服务器端进入CLOSE_WAIT状态,这时服务器端开始收尾工作,把还需要传给客户端的数据传过去,当客户端收到服务器端发送的ACK报文,客户端状态变为FIN_WAIT_2,接收服务器端传过来的数据,当服务器端收尾完成,执行CLOSE命令,向客户端发送一个FIN报文,状态变为LAST_ACK,当客户端收到FIN报文后立刻回传ACK报文,当服务器端收到ACK报文,则释放连接,客户端在发送完ACK报文后,变为TIME_WAIT(2MSL),客户端等待两个MSL的时间,即一个报文来回的时间,然后再释放资源

为什么客户端要等待两个MSL的时间呢?

假设一下,当客户端在发出ACK之后就释放了资源,但是ACK报文丢失了,服务器端就不会关闭,而是持续重复发送FIN报文,客户端也没法响应

第二种情况,客户端释放了资源,但是还有报文在发送过程中,由于释放了资源,端口号就会被其他进程使用,当报文到达,就会对新建立的连接造成混乱

字节流的协议

TCP把应用交付的数据仅仅看成是一连串的无结构的字节流,TCP并不知道字节流的含义,TCP并不关心应用程序一次将多大的报文发送到TCP的缓存中,而是根据对方给出的窗口值和当前网络拥堵的程度来决定一个报文段应该包含多少个字节。

MSS:Max Segment Size,默认536byte实际数据

681e21e96dd66a53160d02350105dc29.png

假设传输20个字节,实际传输的数据要比20个字节大的多,这里为了方便理解,就使用20个字节来讲解,这20个字节有可能会发生这种情况,网络速度比较快的情况下,有一部分数据已经到了应用程序,有一部分还在传输的路上,看到这里就知道,数据并不是一次发过去的,而是把数据分割为很多TCP的报文段,报文段的大小就是MSS,MSS是会根据窗口大小与网络状态去动态的调整的,TCP协议不会在意发多大的数据,无论多大它都会切割成小的报文传输,报文传输过程中会经过非常多的路由器,并且顺序都是不固定的,最终到达服务器,所以报文的顺序是乱的,因此TCP还会进行排序,保证顺序和传进来时是一样的,怎么排序呢?其实就是根据报文的Sequence number序列号来实现的,并且在网络的传输过程中还会发生丢包,如路由器的缓存区满了,还在向路由器加数据,就会丢失,客户端一定时间内还没有接收到TCP协议发送的ACK消息的话,就会重传,有的时候数据没有丢失,而是在路径中没有到达,这时重传就会发生数据重复,因此TCP协议还实现了去重工作,收到了和之前一样的数据会进行丢弃。

数据可靠性传输

停止等待协议:

f132c2ea9fcca8f24de533825e764460.png

每发送一个报文都需要回一个应答,接收到才能发送下一条报文,这种效率很低

重传机制

ACK报文丢失

4f65ad51698b79d8565900bd1725ac37.png

ACK报文丢失,客户端一段时间没有收到ACK报文,客户端会认为ACK报文丢失了,会进行重传M1报文

请求报文丢失

c6b506fcbd20019da432453bdc235b01.png

请求报文丢失,一样没有收到ACK报文,进行重传

滑动窗口协议与累计确认(延时ACK)

滑动窗口大小同通过TCP三次握手和对端协商,且受网络状况影响

d5d73e65f6bb51fe99f3150a2c1329ca.png

Richard Clayderman - 梦中的婚礼

02:43来自编程阶级III

取代了一条一条报文去发送,而是发送窗口大小的报文,只要客户端收到末尾报文的ACK就能确定之前的都到了,但在数据传输过程中会出现丢包的情况,如果3和5丢失了,那么接收4的ACK肯定是不正确的,所以TCP会回传连续的最后一个报文的ACK,服务器端会丢弃3、4和5报文,客户端就会知道1和2已经发送到服务器端,在缓存中删除1和2,从3向后取窗口大小的报文发送到服务器端。

举报/反馈

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值