博客整理day27
python day27
subprocess模块
subprocess:
可以通过代码,去执行系统的终端命令,并返回终端执行命令后的结果
import subprocess
cmd = input('cmd:')
obj = subprocess.Popen(
cmd,
#Shell=True
shell = True
#返回正确结果参数
stdout = subprocess.PIPE
#返回错误结果参数error
stderr = subprocess.PIPE
)
result = obj.stdout.read()+obj.stderr.read()
print(reault.decode('gbk'))
粘包
粘包问题:
服务端第一次发送的数据,与客户端无法精确一次性接收完毕,下一次发送的数据与上一次数据粘在一起了
1.无法预知对方需要接收的数据大小
2.多次连续发送数据量小,并且时间间隔短的数据会一次性打包发送
TCP协议特性:
tcp是一个流式协议,会将多次连续发送数据量小,并且时间间隔短的数据一次性打包发送
解决粘包问题:
struct模块
必须先定义报头,发送报头,再发送真实数据
当既想发送文件,又想发送文件的描述信息
客户端发送字典给服务端
send_dic = {
file_name : 文件名
file_size : 文件的真实长度
}
#通过json模块序列化成bytes数据
json_data = json.dumps(send_dic)
bytes_data = json_data.encode('utf8')
#先获取字典的报头
headers = struct.pack('i',len(bytes_data))
#服务端接收到字典,并接收文件的真实数据
import socket
import struct
import subprocess
server = socket.socket()
server.bind(('192.168.13.161',8888))
server.listen(5)
while True:
conn,addr = server.accept()
while True:
try:
cmd = conn.recv(1024).decode('utf8')
if cmd == 'q':
break
if len(cmd)==0:
continue
print(cmd)
obj = subprocess.Popen(
cmd,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
result = obj.stdout.read()+obj.stderr.read()
headers = struct.pack('i',len(result))
conn.send(result)
except Exception as e:
print(e)
break
conn.close()
上传大文件
客户端往服务端上传大文件:
#Client
import socket
import json
import struct
client = socket.socket()
client.connect(('192.168.13.202', 9526))
with open(r'E:\the truth that you leave.mp3','rb') as f:
music_bytes = f.read()
send_dic = {
'file_name':'the truth that you leave.mp3',
'file_size':len(music_bytes)
}
json_data = json.dumps(send_dic)
bytes_data = json_data.encode('utf8')
headers = struct.pack('i',len(bytes_data))
client.send(headers)
client.send(bytes_data)
init_data = 0
with open(r'E:\the truth that you leave.mp3','rb') as f:
while init_data<len(music_bytes):
send_data = f.read(1024)
print(send_data)
client.send(send_data)
init_data += len(send_data)
client.close()
#Server
import socket
import struct
import json
server = socket.socket()
server.bind(('192.168.13.202', 9526))
server.listen(5)
while True:
conn, addr = server.accept()
try:
headers = conn.recv(4)
data_len = struct.unpack('i', headers)[0]
bytes_data = conn.recv(data_len)
back_dic = json.loads(bytes_data.decode('utf8'))
file_name = back_dic.get('file_name')
file_size = back_dic.get('file_size')
init_data = 0
with open(file_name, 'wb') as f:
while init_data < file_size:
data = conn.recv(1024)
f.write(data)
init_data += len(data)
print(f'{file_name}接收完毕!')
except Exception as e:
print(e)
break
conn.close()
UDP
udp是一种传输协议
1.不需要建立双向管道
2.不会粘包
3.客户端给服务端发送数据,不需要等待服务端返回成功
4.数据容易丢失,数据不安全
TCP : 就好比打电话
UDP : 就好比发短信
QQ聊天室(基于UDP)
#Server
import socket
server = socket.socket()
server.bind(('192.168.13.202', 9526))
while True:
msg,addr = server.recvfrom(1024)
print(addr)
print(msg.decode('utf-8'))
send_msg = input('server-->client:').encode('utf8')
server.sendto(send_msg,addr)
#Client
import socket
client = socket.socket()
server_port = (('192.168.13.202', 9526))
while True:
send_msg = input('client -- > server:').encode('utf8')
msg = client.recv(1024)
print(msg.decode('utf-8'))
socketServer
python内置模块,可以简化socket套接字服务端的代码
- 简化TCP与UDP服务端代码
- 必须要创建一个类
import socketserver
# 定义类
# TCP: 必须继承BaseRequestHandler类
class MyTcpServer(socketserver.BaseRequestHandler):
# 必须重写父类的handle
def handle(self):
# 1.接收消息
print(data)
# 2.给客户端发送消息
send_msg = input('服务端: ').encode('utf-8')
self.request.send(send_msg)
if __name__ == '__main__':
socketserver.TCPServer.allow_reuse_address = True
server = socketserver.TCPServer(
('192.168.13.202', 9526), MyTcpServer
)
# 永久执行服务
server.serve_forever()