day31——recv工作原理、高大上版解决粘包方式、基于UDP协议的socket通信

2022-12-07,,,,

day31

recv工作原理

源码解释:
Receive up to buffersize bytes from the socket.
接收来自socket缓冲区的字节数据,
For the optional flags argument, see the Unix manual.
对于这些设置的参数,可以查看Unix手册。
When no data is available, block untilatleast one byte is available or until the remote end is closed.
当缓冲区没有数据可取时,recv会一直处于阻塞状态,直到缓冲区至少有一个字节数据可取,或者远程端关闭。
When the remote end is closed and all data is read, return the empty string.
关闭远程端并读取所有数据后,返回空字符串。

高大上版解决粘包方式(自定制报头)

我们要制作固定的报头

你现在有两段不固定长度的bytes类型,我们要固定的报头,所以

你获取不固定报头的长度
利用struct模块将不固定的长度转化成固定的字节数4个字节
先发4个字节,再发报头数据,再发总数据

server
import socket
import subprocess
import struct
import json
phone = socket.socket()
phone.bind(("127.0.0.1",8080))
phone.listen(3)
while 1:
conn, addr = phone.accep()
print(f"{addr}客户端链接了")
while 1:
try:
from_client_data = conn.recv(1024)
obj = subprocess.Popen(from_client_data.decode("utf-8"),
shell = True,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE
)
data = obj.stdout.read() + obj.stderr.read()
data_len = len(data) # 1、自定义报头
head_dic = {
"file_name": "test1",
"md5": 654654654654,
"total_size": data_len
} # 2、json形式的报头
head_dic_json = json.dumps(head_dic) # 3、bytes形式的报头
head_dic_json_bytes = head_dic_json.encode("utf-8") # 4、bytes形式的报头的总字节数
len_head_dic_json_bytes = len(head_dic_json_bytes) # 5、把报头的总字节数变成固定的4个字节
four_head_bytes = struct.pack("i", len_head_dic_json_bytes) # 6、发送固定的4个字节
conn.send(four_head_bytes) # 7、发送bytes形式的报头
conn.send(head_dic_json_bytes) # 8、发送总数据
conn.send(data)
exctpt Exception:
print(f"{addr}客户端关闭!")
break
conn.close()
phone.close()
client
import socket
import struct
import json
phone = socket.socket()
phone.connect(("127.0.0.1", 8080))
while 1:
data = input("请输入>>>")
if not data:
print("输入内容不为空!")
continue
phone.send(data.encode("utf-8"))
if data.upper() == "Q":
print("通信关闭")
break # 1、获取报头的固定4个字节
four_head_bytes = phone.recv(4) # 2、把固定的4个字节变成bytes形式的报头的总字节数
len_head_dic_json_bytes = struct.unpack("i", four_head_bytes)[0] # 3、获取到bytes形式的报头
head_dic_json_bytes = phone.recv(len_head_dic_json_bytes) # 4、获取json形式的报头
head_dic_json = head_dic_json_bytes.decode("utf-8") # 5、获取报头
dic = json.loads(head_dic_json) # 6、获取总数据长度
data_len = dic["total_size"] # 7、定义一个空字节
data_deposit = b"" # 8、循环获取总数据
while len(data_deposit) < data_len:
data_deposit += phone.recv(1024)
# 把总数据转成源数据
print(data_deposit.decode("gbk"))
phone.close()

基于UDP协议的socket通信

多人在服务器聊天

server

import socket
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server.bind(("127.0.0.1", 9000)) while True:
conn, addr = server.recvfrom(1024)
print(f"来自{addr}的消息:{conn.decode('utf-8')}")

client

import socket
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) while True:
data = input(">>>")
client.sendto(data.encode("utf-8"), ("172.0.0.1", 8080))
服务器与多人聊天

server

import socket
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server.bind(("127.0.0.1", 9000)) while True:
conn, addr = server.recvfrom(1024)
print(f"来自{addr}的消息:{conn.decode('utf-8')") data = input(">>>")
server.sendto(data.encode("utf-8"), addr)

client

import socket
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) while True:
data = input(">>>")
client.sendto(data.encode("utf-8"), ("127.0.0.1", 9000)) conn, addr = client.recvfrom(1024)
print(f"来之{addr}的消息:{conn.decode('utf-8')}")

day31——recv工作原理、高大上版解决粘包方式、基于UDP协议的socket通信的相关教程结束。

《day31——recv工作原理、高大上版解决粘包方式、基于UDP协议的socket通信.doc》

下载本文的Word格式文档,以方便收藏与打印。