서브 프로세스 모듈
: 액션
1 단말은 운영 시스템 코드 실행 명령 수
(2)의 결과를, 상기 단말기는 실행을 반환
用法:
import subprocess
cmd = inpu('CMD >>>')
obj = subprocess.Popen(
cmd.decode('utf8'),
shell=True,
stdout= subprocess.PIPE,
stderr= subprocess.PIPE
)
result = obj.stdout.read() + obj.stderr.read()
print(result.decode('gbk'))
TCP 프로토콜
특성 : 이것은 스트리밍 프로토콜, 적은 양의 데이터가 연속적으로 송신 할 복수 회, 하나 개의 시간 간격이 짧은 데이터 패키지가 전송되는이며
패키지 끈적 문제
이유 :
(1) 수신 된 데이터의 길이가 필요로 예측할 수
2 연속 데이터 전송량 복수 작고, 데이터의 짧은 시간 간격은 일회용 포장을 전송.
패키지는 끈적 문제를 해결하기 위해 : 데이터의 끝의 정확한 길이를 말한다.
-struct 모듈 :
헤더, 데이터 전송되어야한다 :
1 커스텀 헤더, 사전에 이러한 기술 정보로서 생성 된 데이터의 데이터 길이는
(2), 사전 json.dumps 직렬화 및 송신 바이트로 부호화
3 상기 제 1 패킷의 헤더의 길이, 다음 struct.pack (4 바이트)와 고정 된 길이로 포맷
4 전송 : 그 1 헤더 길이, 다음의 전송 헤더를 전송하고, 상기 데이터 본체를 보낸다
수신 :
도 1을 참조하면, 먼저 네 개의 바이트 헤더의 길이 정보는 헤더의 길이 값을 압축하는 압축하는 접수
2. json.load 얻어진 수신 된 헤더의 헤더 값, 및 디코딩 된 텍스트 데이터의 길이 (데이터 길이를 포함)의 설명 정보를 직렬화
(3) 본체의 데이터 길이에 따라 상기 수신 된 데이터,
사용법 :
import json,struct
#假设通过客户端上传10G:10000000的文件:小视频.txt
#为避免粘包,必须自定制报头
header={'file_size':10000000,'file_name':'小视频.txt', 'md5':'8f6fbf8347faa4924a76856701edb0f3'} #10G数据,文件路径和md5值
#为了该报头能传送,需要序列化并且转为bytes
head_bytes=bytes(json.dumps(header),encoding='utf-8') #序列化并转成bytes,用于传输
#为了让客户端知道报头的长度,用struck将报头长度这个数字转成固定长度:4个字节
head_len_bytes=struct.pack('i',len(head_bytes)) #这4个字节里只包含了一个数字,该数字是报头的长度
#客户端开始发送
conn.send(head_len_bytes) #先发报头的长度,4个bytes
conn.send(head_bytes) #再发报头的字节格式
conn.sendall(文件内容) #然后发真实内容的字节格式
#服务端开始接收
head_len_bytes=s.recv(4) #先收报头4个bytes,得到报头长度的字节格式
x=struct.unpack('i',head_len_bytes)[0] #提取报头的长度
head_bytes=s.recv(x) #按照报头长度x,收取报头的bytes格式
header=json.loads(json.dumps(header)) #提取报头
#最后根据报头的内容提取真实的数据,比如
real_data_len=s.recv(header['file_size'])
s.recv(real_data_len)
큰 파일을 업로드
예를 들어 비디오를 업로드하려면 :
클라이언트 :
import socket
import struct
import json
client = socket.socket()
client.connect(
('127.0.0.1', 9527)
)
with open(r'C:\day 027\5 上传大文件.mp4', 'rb')as f:
movie_bytes = f.read()
head_dic = {
'file_name': '5 上传大文件.mp4',
'file_size': len(movie_bytes)
}
json_head = json.dumps(head_dic)
bytes_head = json_head.encode('utf-8')
headers = struct.pack('i', len(bytes_head))
client.send(headers)
client.send(bytes_head)
init_data = 0
num = 1
with open(r'C:\day 027\5 上传大文件.mp4', 'rb')as f:
while init_data < len(movie_bytes):
send_data = f.read(1024)
num += 1
client.send(send_data)
print(send_data, f'第{num}段数据发送完成')
init_data += len(send_data)
print('发送完毕!')
서버 :
import socket
import json
import struct
server = socket.socket()
server.bind(
('127.0.0.1', 9527)
)
server.listen(5)
while True:
conn, addr = server.accept()
try:
headers = conn.recv(4)
head_len = struct.unpack('i', headers)[0]
byte_head = conn.recv(head_len)
head_dic = json.loads(byte_head.decode('utf-8'))
print(head_dic)
file_name = head_dic.get('file_name')
file_size = head_dic.get('file_size')
init_data = 0
num = 1
with open(file_name, 'wb') as f:
while init_data < file_size:
data = conn.recv(1024)
print(f'第{num}段',data)
f.write(data)
init_data += len(data)
print(f'{file_name}接收完毕!')
except Exception as e:
print('error:', e)
break
conn.close()
UDP
UDP는 전송 프로토콜
양방향 파이프를 확립 할 필요가 없습니다, 1
2,하지 끈적 가방
말에 서비스를 기다리지 않고 3, 클라이언트가 서버에게 데이터의 수신을 보냅니다
4, 서버는 데이터만을 수신 할 필요가 수신 아무리 많은 고객이 통과 오지
서버 :
import socket
server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(
('127.0.0.1', 9527)
)
msg1 = server.recvfrom(1024)
msg2 = server.recvfrom(1024)
msg3 = server.recvfrom(1024)
print(msg1, msg2, msg3)
클라이언트 :
import socket
client =socket.socket(type=socket.SOCK_DGRAM)
server_ip_port = ('127.0.0.1', 9527)
client.sendto(b'hello!', server_ip_port)
client.sendto(b'hello!', server_ip_port)
client.sendto(b'hello!', server_ip_port)
client.sendto(b'hello!', server_ip_port)
client.sendto(b'hello!', server_ip_port)
결과 : (b'hello '('127.0.0.1 ', 57182) (b'hello!)'( '127.0.0.1', 57182)) (b'hello '('127.0.0.1 '! , 57182))
간단한 채팅 룸
여러 클라이언트 간단한 채팅 룸에 대한 소켓 서버 소켓을 구현하는 TCP 프로토콜을 기반으로 :
서버 :
import socket
server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(
('127.0.0.1', 9527)
)
while True:
# 服务端接收客户端传过来的消息
msg, addr = server.recvfrom(1024) # (消息,客户端地址)
msg1, addr1 = server.recvfrom(1024) # (消息,客户端地址)
msg2, addr2 = server.recvfrom(1024) # (消息,客户端地址)
print(addr)
print(addr1)
print(addr2)
print(msg.decode('utf-8'))
print(msg1.decode('utf-8'))
print(msg2.decode('utf-8'))
# 服务端往客户端发送消息
send_msg = input('服务端发送消息:').encode('utf-8')
server.sendto(send_msg, addr)
server.sendto(send_msg, addr1)
server.sendto(send_msg, addr2)
클라이언트 1 :
import socket
client = socket.socket(type=socket.SOCK_DGRAM)
server_ip_port = ('127.0.0.1', 9527)
while True:
send_msg = input('客户端1: ').encode('utf-8')
# 发送消息必须要加上对方地址
client.sendto(send_msg, server_ip_port)
# 能接收任何人的消息
msg = client.recv(1024)
print(msg.decode('utf-8'))
클라이언트 2 :
import socket
client = socket.socket(type=socket.SOCK_DGRAM)
server_ip_port = ('127.0.0.1', 9527)
while True:
send_msg = input('客户端2: ').encode('utf-8')
# 发送消息必须要加上对方地址
client.sendto(send_msg, server_ip_port)
# 能接收任何人的消息
msg = client.recv(1024)
print(msg.decode('utf-8'))
클라이언트 3 :
import socket
client = socket.socket(type=socket.SOCK_DGRAM)
server_ip_port = ('127.0.0.1', 9527)
while True:
send_msg = input('客户端3: ').encode('utf-8')
# 发送消息必须要加上对方地址
client.sendto(send_msg, server_ip_port)
# 能接收任何人的消息
msg = client.recv(1024)
print(msg.decode('utf-8'))
먼저 서버를 시작한 다음 차례에서 클라이언트를 시작, 시뮬레이션 대화방을 시작할 수 있습니다
SocketServer
파이썬은 내장 된 모듈은 소켓 소켓 서버 코드를 단순화하는 데 사용할 수있다
import socket
class MyTcpServer(socketserver, BaseRequestHandler):
def handler(self):
data = self.request.recv(1024)
pirnt(data)
send_msg = input('服务端:').encode('utf8')
self.request.send(send_msg)