网络传输协议 UDP & TCP 详解
UDP协议&TCP协议
二者均位于OSI中的传输层,用于处理数据包的网络传输层协议
UDP协议(用户数据报协议)User Datagram Protocol
- 1、是⼀个⽆连接的简单的⾯向数据报的传输层协议。 UDP不提供可靠性, 它只是把应⽤程序传给IP层的数据报发送出去, 但是并不能保证它们能到达⽬的地。 由于UDP在传输数据报前不⽤在客户和服务器之间建⽴连接, 且没有超时重发等机制, 故⽽传输速度很快
- 2、UDP⼀般⽤于多点通信和实时的数据业务, ⽐如:
语⾳⼴播
视频
QQ
TFTP(简单⽂件传送)
- 可以理解为写信
UDP基本语法
# 客户端
import socket
# 1、创建'UDP'协议下的套接字对象
# 'type=socket.SOCK_DGRAM' 返回 'UDP'协议对象
sk = socket.socket(type=socket.SOCK_DGRAM)
# 2、向服务端发送数据
# 格式为:'UDP'协议对象.sendto(二进制字节流形式的消息数据, 服务端的(ip, port))
# 客户端在向服务端发送消息时,会将客户端的(ip + port)发送到服务端
# 端口是随机分配
msg = "你好!"
sk.sendto(msg.encode(), ("127.0.0.1", 8866))
# 3、客户端接收服务端发送过来的数据
msg, server_addr = sk.recvfrom(1024)
print(msg.decode())
print(server_addr)
# 4、退还端口,关闭套接字
sk.close()
# 服务端
import socket
# 1、创建'UDP'协议下的套接字对象
sk = socket.socket(type=socket.SOCK_DGRAM)
# 2、绑定服务端地址(ip + port)
sk.bind(("127.0.0.1", 8866))
# 3、'UDP'协议下的'socket'编程,服务端是先接受消息
msg, client_addr = sk.recvfrom(1024)
print(msg.decode())
print(client_addr)
# 4、服务端给客户端回复消息
msg = "你好呀!"
sk.sendto(msg.encode(), client_addr)
# 5、退还端口,关闭套接字
sk.close()
TCP协议(传输控制协议)Transmission Control Protocol
-
1、是一种面向连接的、可靠的、基于字节流的传输层通信协议,面向连接意味着两个使用TCP的应用(通常是一个客户端和一个服务器)在彼此交换数据包之前必须先建立一个TCP连接
-
2、TCP连接必须要经过三次握手才能建立起来,其中的过程如下:
-
第一次握手:客户端先发送 SYN(SEQ=x)报文(请求同步)到服务端,并且进入
SYN_SENT(请求连接)状态
,等待服务器确认; -
第二次握手:服务端收到客户端发送过来的请求同步的 SYN报文之后,给客户端发送 同意连接 的 ACK(ACK=x+1)报文 ACK(确认响应);同时也给客户端发送一个请求同步的 SYN (SEQ=y)报文,此时服务端进入
SYN_RECV(SYN派遣状态)
; -
第三次握手:客户端收到服务端发送的SYN + ACK两个报文之后,向服务端发送确认连接的ACK(ACK=y+1)报文,等此包发送完毕,客户端与服务端进入
ESTABLISHED(TCP连接成功)状态
,完成三次握手,客户端与服务端正式开始传输数据
图解如下:
-
-
3、终止一个TCP连接要经过四次挥手,其过程如下:
-
第一次挥手:主动关闭方
(active close)
调用close,会发送一个长度为0的数据包以及FIN分节(结束标志)用来关闭主动方与被动关闭方之间的数据传输,告诉被动关闭方:我不会再给你发数据了,但是,此时主动关闭方还可以接受数据; -
第二次挥手:被动关闭方收到FIN分节后,发送一个ACK给对方,确认序号为收到序号 + 1;
-
第三次挥手:被动关闭方再给主动关闭方发送一个FIN,用来关闭被动关闭方与主动关闭方之间的数据传输,也就是告诉主动关闭方,我的数据也发送完了,不会再给你发数据了;
-
第四次挥手:主动关闭方收到FIN后,发送一个ACK给被动关闭方,确认序号为收到序号 + 1,至此,完成四次挥手。
图解如下:
注意:TCP通过下列方式来提供可靠性:
-
1.应用数据被分割成TCP认为最适合发送的数据块。这和UDP完全不同,应用程序产生的数据长度将保持不变。由TCP传递给IP的信息单位称为报文段或段(segment)。
2.当TCP发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。当TCP收到发自TCP连接另一端的数据,它将发送一个确认。TCP有延迟确认的功能,在此功能没有打开,则是立即确认。功能打开,则由定时器触发确认时间点。
3.TCP将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP将丢弃这个报文段和不确认收到此报文段(希望发端超时并重发)。
4.既然TCP报文段作为IP数据报来传输,而IP数据报的到达可能会失序,因此TCP报文段的到达也可能会失序。如果必要,TCP将对收到的数据进行重新排序,将收到的数据以正确的顺序交给应用层。
5.既然IP数据报会发生重复,TCP的接收端必须丢弃重复的数据。
6.TCP还能提供流量控制。TCP连接的每一方都有固定大小的缓冲空间。TCP的接收端只允许另一端发送接收端缓冲区所能接纳的数据。这将防止较快主机致使较慢主机的缓冲区溢出。
汇总图解:
TCP基本语法
# 客户端
import socket
# 1、创建'TCP'协议下的套接字对象
# 'type=socket.SOCK_STREAM'可以省略
sk = socket.socket(type=socket.SOCK_STREAM)
# 2、客户端与服务端建立连接
sk.connect(("127.0.0.1", 6688))
# 3、客户端向服务端发送数据(二进制的字节流)
msg = "你好!"
sk.send(msg.encode("utf-8"))
# 4、退还端口,关闭套接字
sk.close()
# 服务端(简易未实现并发)
import socket
# 1、创建'TCP'协议下的套接字对象
sk = socket.socket()
# 2、服务端绑定(ip + port)注册网络
sk.bind(("127.0.0.1", 6688))
# 3、服务端将套接字对象设置为监听状态,并设置最大连接数
sk.listen(5)
# 4、通过三次握手建立连接
# 等待客户端请求连接,一旦建立了连接,'accpet'方法会返回一个新的套接字对象,和客户端的IP地址和端口号
conn, client_addr = sk.accept()
# 5、进行数据收发
# recv里面的参数表示一次最多接受多少字节的数据
msg = conn.recv(1024)
print(msg.decode("utf-8"))
# 6、四次挥手关闭连接
conn.close()
# 7、退还端口,关闭套接字
sk.close()
二者的区别:
- 1、
TCP 是面向连接的传输控制协议,而UDP 提供了无连接的数据报服务
; - 2、
TCP 具有高可靠性,确保传输数据的正确性,不出现丢失或乱序
; - 3、
UDP 在传输数据前不建立连接,不对数据报进行检查与修改,无须等待对方的应答,所以会出现分组丢失、重复、乱序,应用程序需要负责传输可靠性方面的所有工作
; - 4、
UDP 具有较好的实时性,工作效率较 TCP 协议高
; - 5、
UDP 段结构比 TCP 的段结构简单,因此网络开销也小
; - 6、
TCP 协议可以保证接收端毫无差错地接收到发送端发出的字节流,为应用程序提供可靠的通信服务
; - 7、
对可靠性要求高的通信系统往往使用 TCP 传输数据。比如 HTTP 运用 TCP 进行数据的传输
。