09-18-周四_10-40-47

This commit is contained in:
2025-09-18 10:40:47 +08:00
parent 4222354358
commit 3ed89009e5

View File

@@ -553,6 +553,67 @@ phone.close()
## 粘包的解决方案
### 添加结束字符
在每次发送一个信息结束的地方,添加一个标识,在从缓冲区获取数据时候,根据表示来判断消息是否已经获取结束
- 服务端
```python
import socket
import subprocess
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.bind(('127.0.0.1', 8080))
phone.listen(5)
while 1: # 循环连接客户端
conn, client_addr = phone.accept()
print(client_addr)
while 1:
try:
cmd = conn.recv(1024)
ret = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
correct_msg = ret.stdout.read()
error_msg = ret.stderr.read()
conn.send(correct_msg + error_msg + "結束".encode("gbk"))
except ConnectionResetError:
break
conn.close()
phone.close()
```
- 客户端
```python
import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 买电话
phone.connect(('127.0.0.1',8080)) # 与客户端建立连接, 拨号
while 1:
cmd = input('>>>')
phone.send(cmd.encode('utf-8'))
from_server_data = b""
while True:
from_server_data += phone.recv(1024)
if from_server_data.decode('gbk').count("結束") > 0:
break
print(from_server_data.decode('gbk'))
phone.close()
```
- 这样只是解决了一次消息没有收完整的情况但是一次接受1024可能会将紧跟的下一条消息的开头也一并接收了
### struct模块
该模块可以把一个类型如数字转成固定长度的bytes
@@ -570,6 +631,8 @@ ret1 = struct.unpack('i',ret)[0]
print(ret1, type(ret1), len(ret1))
# 但是通过struct 处理不能处理太大
# 可处理的范围是 -2,147,483,648 ~ 2,147,483,647即 -2³¹ ~ 2³¹-1
# 如果超出范围就会发生异常struct.error
```
方案一:
@@ -643,7 +706,12 @@ while 1:
res = b''
while recv_size < total_size:
recv_data = phone.recv(1024)
# 精准的获取数据的长度,防止将后面跟着的数据头部获取到
if (total_size - recv_size) > 1024:
recv_buffer = 1024
else:
recv_buffer = total_size - recv_size
recv_data = phone.recv(recv_buffer)
res += recv_data
recv_size += len(recv_data)
@@ -757,13 +825,19 @@ while 1:
res = b''
while recv_size < total_size:
recv_data = phone.recv(1024)
# 精准的获取数据的长度,防止将后面跟着的数据头部获取到
if (total_size - recv_size) > 1024:
recv_buffer = 1024
else:
recv_buffer = total_size - recv_size
recv_data = phone.recv(recv_buffer)
res += recv_data
recv_size += len(recv_data)
print(res.decode('gbk'))
phone.close()
```
FTP上传下载文件的代码简单版
@@ -775,7 +849,6 @@ import socket
import struct
import json
sk = socket.socket()
## buffer = 4096 # 当双方的这个接收发送的大小比较大的时候就像这个4096就会丢数据这个等我查一下再告诉大家改小了就ok的在linux上也是ok的。
buffer = 1024 #每次接收数据的大小
sk.bind(('127.0.0.1',8090))
sk.listen()
@@ -794,9 +867,10 @@ with open(head['filename'],'wb') as f:
f.write(content)
filesize -= buffer
else:
content = conn.recv(buffer)
content = conn.recv(filesize)
f.write(content)
break
print(head['filename'], "接收成功")
conn.close()
sk.close()
@@ -813,15 +887,14 @@ sk = socket.socket()
sk.connect(('127.0.0.1',8090))
buffer = 1024 #读取文件的时候,每次读取的大小
head = {
'filepath':r'C:\Users\Aaron\Desktop\新建文件夹', #需要下载的文件路径,也就是文件所在的文件夹
'filename':'config', #改成上面filepath下的一个文件
'filepath':r'C:\Users\simid\Desktop', #需要下载的文件路径,也就是文件所在的文件夹
'filename':'KKRIEGER.EXE', #改成上面filepath下的一个文件
'filesize':None,
}
file_path = os.path.join(head['filepath'],head['filename'])
filesize = os.path.getsize(file_path)
head['filesize'] = filesize
# json_head = json.dumps(head,ensure_ascii=False) #字典转换成字符串
json_head = json.dumps(head) #字典转换成字符串
bytes_head = json_head.encode('utf-8') #字符串转换成bytes类型
print(json_head)