文件上传下载-UDP协议-socketserver并发
recv原理
1.验证服务端缓冲区数据没有取完,又执行了recv执行,recv会继续取值。
# 服务器:
import socket
phone =socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.bind(('127.0.0.1',8080))
phone.listen(5)
conn, client_addr = phone.accept()
from_client_data1 = conn.recv(2)
print(from_client_data1)
from_client_data2 = conn.recv(2)
print(from_client_data2)
from_client_data3 = conn.recv(1)
print(from_client_data3)
conn.close()
phone.close()
# 客户端:
import socket
import time
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(('127.0.0.1',8080))
phone.send('hello'.encode('utf-8'))
time.sleep(20)
phone.close()
2.验证服务端缓冲区取完了,又执行了recv执行,此时客户端20秒内不关闭的前提下,recv处于阻塞状态
# 服务端:
import socket
phone =socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.bind(('127.0.0.1',8080))
phone.listen(5)
conn, client_addr = phone.accept()
from_client_data = conn.recv(1024)
print(from_client_data)
print(111)
conn.recv(1024) # 此时程序阻塞20秒左右,因为缓冲区的数据取完了,并且20秒内,客户端没有关闭。
print(222)
conn.close()
phone.close()
# 客户端:
import socket
import time
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(('127.0.0.1',8080))
phone.send('hello'.encode('utf-8'))
time.sleep(20)
phone.close()
3. 服务端缓冲区的数据取完之后,又执行了recv执行,此时客户端处于关闭状态,则recv会取到空字符串。
# 服务端:
import socket
phone =socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.bind(('127.0.0.1',8080))
phone.listen(5)
conn, client_addr = phone.accept()
from_client_data1 = conn.recv(1024)
print(from_client_data1)
from_client_data2 = conn.recv(1024)
print(from_client_data2)
from_client_data3 = conn.recv(1024)
print(from_client_data3)
conn.close()
phone.close()
# 客户端:
import socket
import time
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(('127.0.0.1',8080))
phone.send('hello'.encode('utf-8'))
phone.close()
用户登录功能实现:
用户登录作业用tcp协议下的socket完成:
1,服务端:
等待客户端来发送数据:用户名,密码。
本地文件汇总查看用户名密码是否合法。
合法:登录成功。
否则:用户名或者密码错误。
2,客户端:
用户输入: 用户名,密码。
发送到服务端进行校验。
服务端:
import socket
server = socket.socket()
server.bind(('127.0.0.1',9045))
server.listen(5)
try:
while 1:
conn,addr = server.accept()
flag = 0
while not flag:
user_pwd = conn.recv(1024).decode('utf-8')
with open ('userinfo',encoding='utf-8')as f:
for i in f:
if i.strip() == user_pwd:
conn.send('success'.encode('utf-8'))
flag =1
break
else:
conn.send('failed'.encode('utf-8'))
conn.close()
finally:
server.close()
客户端:
import socket
client = socket.socket()
client.connect(('127.0.0.1',9045))
while 1:
user = input('用户名>>>').strip()
pwd = input('密码>>>').strip()
user_pwd = user + '|' + pwd
client.send(user_pwd.encode('utf-8'))
result = client.recv(1024)
if result == b'success':
print('登录成功')
break
else:
print('用户名或密码错误')
client.close()
上传功能实现:
服务端:
import socket
import json
import struct
import os
server = socket.socket()
server.bind(('127.0.0.1',9345))
server.listen()
file_base_path = 'D:\上传下载'
conn,addr = server.accept()
head_dic_json_bytes_struct = conn.recv(4) #接收4个字节
head_dic_json_bytes_len = struct.unpack('i',head_dic_json_bytes_struct)[0] # 转换成int长度
head_dic_json_bytes = conn.recv(head_dic_json_bytes_len) # 接收报头字典的字节
head_dic_json = head_dic_json_bytes.decode('utf-8') # 转换成json字符串
head_dic = json.loads(head_dic_json) # 转换成报头字典
file_path = os.path.join(file_base_path,head_dic['file_name'])
with open(file_path,mode='wb')as f:
total_data_size = 0
while total_data_size < head_dic['file_size']:
every_data = conn.recv(1024)
f.write(every_data)
total_data_size += len(every_data)
conn.close()
server.close()
客户端:
import socket
import json
import struct
import os
client = socket.socket()
client.connect(('127.0.0.1',9345))
#1.自定制报头
head_dic = {
'file_name':'今日总结.mp4',
'file_path':r'F:\workspace_python\s19\day30\文件上传\今日总结.mp4',
'file_size':None
}
head_dic['file_size'] = os.path.getsize(head_dic['file_path'])
head_dic_json =json.dumps(head_dic) #转换成json字符串
head_dic_json_bytes = head_dic_json.encode('utf-8') #将字符串转换成字节
head_dic_json_bytes_struct = struct.pack('i',len(head_dic_json_bytes)) #转换成4个字节
client.send(head_dic_json_bytes_struct)
client.send(head_dic_json_bytes)
with open(head_dic['file_name'],mode='rb')as f1:
total_data_size = 0
while total_data_size < head_dic['file_size']:
every_data = f1.read(1024)
client.send(every_data)
total_data_size += len(every_data)
client.close()
基于UDP协议的socket
TCP协议有回执,丢包跟网络相关(网络断开或者遭遇抓包)
UDP协议无阻塞,没有粘包现象
服务端:
import socket
server = socket.socket(type=socket.SOCK_DGRAM) # udp协议
server.bind(('127.0.0.1',8848))
try:
while 1:
client_data, client_address = server.recvfrom(1024)
print('来自%s消息: %s'%(client_address,client_data.decode('utf-8')))
to_client_data = input('回复:').strip().encode('utf-8')
server.sendto(to_client_data,client_address)
finally:
server.close()
客户端:
import socket
client = socket.socket(type=socket.SOCK_DGRAM) # udp协议
while 1:
to_server_data = input('给服务端发送:').strip().encode('utf-8')
client.sendto(to_server_data,('127.0.0.1',8848))
server_data, server_address = client.recvfrom(1024)
print('\033[1;35;0m来自%s的信息: %s\033[0m' %(server_address,server_data.decode('utf-8')))
socketserver
服务端:
import socketserver
class MyServer(socketserver.BaseRequestHandler): # MyServer类名不固定,但是必须要继承socketserver.BaseRequestHandler
def handle(self): # handle方法名固定写法
# self.request conn
while 1:
from_client_data = self.request.recv(1024)
print(from_client_data.decode('utf-8'))
to_client_data = input('>>>').strip().encode('utf-8')
self.request.send(to_client_data)
if __name__ == '__main__':
ip_port = ('127.0.0.1', 8888)
socketserver.TCPServer.allow_reuse_address = True
server = socketserver.ThreadingTCPServer(ip_port,MyServer) # 固定写法((ip地址,端口),MyServer)
# 源码显示:上一行代码: 创建socket对象,绑定ip地址和端口,监听
server.serve_forever()
客户端:
import socket
client = socket.socket()
client.connect(('127.0.0.1',8888))
while 1:
to_server_data = input('>>>').strip().encode('utf-8')
client.send(to_server_data)
from_server_data = client.recv(1024).decode('utf-8')
print(from_server_data)


浙公网安备 33010602011771号