09-18-周四_10-40-47
This commit is contained in:
@@ -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)
|
||||
|
Reference in New Issue
Block a user