看到有人说TCP/IP协议与UDP协议的区别被一群人吐槽了,网络编程的知识仅仅是在以前学习java基础中的socket编程中写的一个小的聊天室,这里回顾下一些基础的网络知识。
首先说下为什么被吐槽,因为TCP/IP叫做网络通讯协议,是一个协议族,并不是表面上指TCP和IP,其中包含了TCP、IP、UDP、ICMP、RIP、TELNET、FTP、SMTP、ARP、TFTP等协议。下面着重的梳理下tcp和udp的知识和它们之间的区别。‘’
在这之前先看下OSI的七层模式:
数据从应用层发下来,会在每一层都会加上头部信息,进行封装,然后再发送到数据接收端。这个是基本的流程,就是每个数据都会经过数据的封装和解封装的过程。
而每一层的作用和对应的协议如下:
因为通常web编程使用的都是tcp协议,所以这里再详细的看下tcp协议头部的格式:
源端口和目标端口(Source Port和Destination Port): 各两个字节,表示源端口号和目的端口号,配合上IP首部中的源IP地址和目的IP地址就能确定唯一TCP连接
封包序号(Sequence Number):四个字节,如果TCP数据太大时,需要进行分段,封包序号就是记录每个封包的序号,可以让接收端重新将tcp的数据组合在一起(序号字段的值则指的是本报文所发送的数据的第一个字节的序号),主要用来解决网络报乱序的问题
确认号(Acknowledgment Number):确定序列号包含发送确认的一端所期望收到的下一个序号,确认序号是上次已成功收到数据字节序号加一,主要用来解决不丢包的问题
数据偏移(Offset):指出TCP报文段的数据起始处距离TCP报文段的起始处有多远,最多可以有60字节的tcp头部
状态控制码(TCP Flags):占六比特,含义如下:
- URG:紧急比特,会加急传送数据(相当于高优先级的数据)
- ACK:确认比特,当为1的时候代表这个封包为确认封包,当为0时,确认号无效
- PSH:表示PUSH操作,当为一的时候,表示无需缓冲满才发送封包
- RST:复位比特,当为1时,表示连接出现严重差错,必须释放连接,然后重新建立运输连接
- SYN:同位比特,当为1时,表示主动要求连接到对方
- FIN:终止比特,用来释放一个连接,当为1时,表示数据发送完毕,并要求释放运输连接
滑动窗口(Window):占两个字节,用来进行流量控制,比较复杂,看不懂
TCP
是面向连接的协议,包含了建立和拆除连接,说到这里就不得不说tcp的三次握手和四次分手(真是缠绵啊)。
这里通俗的理解下三次握手:
客户端:hi,吃了么?
服务端:吃了,你呢?
客户端:还没有。
三次对话的目的是同步连接双方的序列号和确认号并交换 TCP窗口大小信息,三次对话之后,才开始发送数据。防止了服务器端的一直等待而浪费资源
三次握手的详细过程如下:
- 第一次握手:建立连接,客户端发送连接请求报文段,将SYN位置为1,Sequence Number为x,然后,客户端进入SYN_SEND状态,等待服务器的确认
- 第二次握手:服务器收到SYN报文段,服务器收到客户端的SYN报文段,需要对这个SYN报文段进行确认,设置Acknowledgment Numer为x+1,同时,自己还要发送SYN请求信息,将SYN位置为1,Sequence Number为y,服务器将上述所有信息放到一个报文段,一并发送给客户端,此时服务器进入到SYN_RECV状态
- 第三次握手:客户端收到服务器的SYN+ACK报文段,然后将Acknowledgment Numer设置为1,向服务器发送ACK报文段,这个报文段发送完毕以后,客户端和服务端都进入到ESTABLISHED状态,完成三次握手
四次分手过程:(这里客户端也可以使服务端)
客户端:表示没有数据要发送
服务端:同意关闭请求
服务端:请求关闭连接
客户端:同意关闭
四次分手的详细过程:
- 第一次分手:主机1(客户端或者服务端)设置Sequence Numer和Acknowledgment Number,向主机2发送一个FIN报文段,此时,主机1进入到FIN_WAIT_1状态,这表示主机1没有数据要发送给主机2了
- 第二次分手:主机2收到了主机1发送的FIN报文段,向主机1回一个ACK报文段,Acknowledgment Number为Sequence Number加1,主机1进入FIN_WAIT_2状态,主机2告诉主机1同意关闭请求
- 第三次分手:主机2向主机1发送FIN报文段,请求关闭连接,同时主机2进入LAST_ACK状态
- 第四次分手:主机1收到主机2发送的FIN报文段,向主机2发送ACK报文段,然后主机1进入到TIME_WAIT状态,主机2收到主机1的ACK报文段后就关闭了连接,此时主机1等待2MSL后依然没有收到回复,则证明Server端正常关闭,主机1也可以关闭连接
为什么要进行四次分手:
首先TCP协议是一中面向连接的、可靠的、基于字节流的运输层通信协议,TCP是全双工模式,这就意味着,当主机1发出FIN报文段时,只是表示主机1已经没有数据要发送了,主机1告诉主机2,它的数据已经全部发送完毕了,但是这个时候主机1还是可以接受来自主机2的数据,当主机2返回ACK报文段时,表示它已经知道主机1没有数据要发送了,就会告诉主机1也没有数据要发送了,之后就会中断TCP的连接。
其中的状态码:
FIN_WAIT_1: 这个状态要好好解释一下,其实FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区别是:FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET即进入到FIN_WAIT_1状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2状态,当然在实际的正常情况下,无论对方何种情况下,都应该马上回应ACK报文,所以FIN_WAIT_1状态一般是比较难见到的,而FIN_WAIT_2状态还有时常常可以用netstat看到。(主动方)
FIN_WAIT_2:上面已经详细解释了这种状态,实际上FIN_WAIT_2状态下的SOCKET,表示半连接,也即有一方要求close连接,但另外还告诉对方,我暂时还有点数据需要传送给你(ACK信息),稍后再关闭连接。(主动方)
CLOSE_WAIT:这种状态的含义其实是表示在等待关闭。怎么理解呢?当对方close一个SOCKET后发送FIN报文给自己,你系统毫无疑问地会回应一个ACK报文给对方,此时则进入到CLOSE_WAIT状态。接下来呢,实际上你真正需要考虑的事情是察看你是否还有数据发送给对方,如果没有的话,那么你也就可以 close这个SOCKET,发送FIN报文给对方,也即关闭连接。所以你在CLOSE_WAIT状态下,需要完成的事情是等待你去关闭连接。(被动方)
LAST_ACK: 这个状态还是比较容易好理解的,它是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也即可以进入到CLOSED可用状态了。(被动方)
TIME_WAIT: 表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后即可回到CLOSED可用状态了。如果FINWAIT1状态下,收到了对方同时带FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。(主动方)
CLOSED: 表示连接中断。
从三次握手和四次分手就可以看的出tcp面向连接的通讯方式大大提高了数据通信的可靠性,使发送数据端和接收端正式传输就有了交互,为数据的正式传输打你下了可靠的基础。
其中TCP协议使用TCP头部的seq num + ack机制可以保证顺序性
UDP
主要有下面六个特点:
1、udp是一个非连接的协议,传输数据之前两个终端不建立连接,udp每次把消息放在队列中,应用程序每次从队列中读取一个消息段、
2、由于不建立连接所以不需要维护连接状态,包括收发状态等,因此一台服务器可以同时收到多个客户端的信息。
3、udp信息的标题很短只有8个字节,相比tcp20个字节信息包的额外开销很小。
4、吞吐量不在受拥挤控制算法的调节,只受应用软件生成数据的速率、传输宽带、源端和终端主机性能的限制。
5、udp使用尽量努力交付,即不保证可靠交付,因此主机不需要位置复杂的连接状态表。
6、udp是面向报文的,发送方的udp对应用程序交下来的报文,在添加首部后就向下交付给IP层。
通过上面的特点可以看出udp应用的场景如下:
- 面向数据报方式
- 网络数据大多为短消息
- 拥有大量Client
- 对数据安全性无特殊要求
- 网络负担非常重,但对于相应速度要求非常高
下面分析下tcp和udp的主要区别:
- 两个分别是基于连接和无连接
- 对系统资源的要求
- udp程序结构比较简单
- 流模式和数据报模式
- tcp能够保证数据正确性、不丢失、无重复且按照顺序到达,udp尽最大努力交付,可能会丢失。
- tcp连接只能是一对一的,但是udp可以进行一对一、一对多、多对多的实现
- tcp实际上将数据看做一连串无结构的字节流,udp是报文的形式,没有拥塞控制,因此网络出现拥塞不会使源主机的发送率降低,对于实时的应用是非常有效的。
- 。。。。
以上就是关于tcp和udp知识的一个简单的回顾。还有一篇非常好的文章:连接