TCP 基于流的协议
又叫可靠性传输协议 通过三次握手 四次挥手 来保证数据传输完毕 缺点效率低
正因为是基于流的协议 所以会出现粘包问题
粘包问题:原因一:是应为数据是先发送给操作系统,在操作系统中有一个缓冲池 ,操作系统并不会马上把数据发送给服务器端的缓冲池,而是在自己的缓冲池中,
操作系统会将数据小,发送间隔短的数据进行底层优化,然后一起发送出去就造成了数据的混合,以至于到了服务器哪里的缓冲池也区分不出来,造成的粘包
原因二,数据发到服务器的缓冲池中,服务器没有及时发送给应用软件接收,造成了在服务器缓冲池中的粘包
根本原因:是因为接收方在接收数据的时候不知道数据的长度是多少,故在服务器的操作系统缓冲池中取不到正确长度的数据,造成了数据取多,或者取少,导致的粘包问题
解决的方法 导入struct模块
客户端:
import socket
import struct
"""
解决粘包的核心思路就是
先通知接收方 要发送的数据的长度
在发送真实数据
问题在于 数据长度 也是不确定的
对方也不清楚 长度信息 到底是几个字节
要想办法 将长度信息所占的字节数 固定下来
"""
c = socket.socket()
c.connect(("127.0.0.1",8888))
# 要发送的数据
data = "{'name':'jerry'}".encode("utf-8")
# 给接收方发送数据的长度
length = len(data)
# 将整型的长度 转为固定长度的字节
len_data = struct.pack("q",length)
# 发送长度信息
c.send(len_data)
# 发送真实数据
c.send(data)
服务器:
import socket
import struct
"""
TCP 的粘包问题
TCP 流式协议
基于数据流的协议
"""
s = socket.socket()
s.bind(("127.0.0.1",8888))
s.listen()
c,addr = s.accept()
# 先接收长度
# 有可能 长度信息和真实数据也黏在一起 无法取出长度信息
# 解决方案是 把长度信息 转换为一个固定字节数的二进制数据
# 1 4个字节的bytes
# 2 4个字节的bytes
# 20000 4个字节的bytes
# 接收数据的长度信息
length = struct.unpack("q",c.recv(8))[0]
print("长度为:%s" % length)
data = c.recv(length).decode("utf-8")
print(data)
UDP 基于数据报的传输协议
传输效率高,但不关心对方是否收到数据 可以放在语音通话 和视频通话上
udp是放在数据帧里面传输的 数据帧最多放1500个字节,除去udp的报头 一个数据帧最多发送1472个字节的udp,如果udp过大
就会被拆分成多个数据帧发送到网络,即会造成丢包的现象