网络编程 文件传输 基于UDP的socket serversocket
基于TCP协议的文件传输
客户端向服务端上传文件
简单版 / 下载与上传
# server
import socket
import struct
import os
import json
import hashlib
file_path = os.path.join(os.path.dirname(__file__),"my_file")
def socket_server():
server = socket.socket()
server.bind(('127.0.0.11',8888))
server.listen(5)
conn,addr = server.accept()
# 1 .接收固定长度的4个字节
four_bytes = conn.recv(4)
# 2.利用struct反解
head_len = struct.unpack('i',four_bytes)[0] # 此处反解后是一个元组
# 3.接收bytes类型的字典
heat_dic_json_bytes = conn.recv(head_len)
# 4.将bytes的字典转化为json
heat_dic_json = heat_dic_json_bytes.decode('utf-8')
# 5.将bytes的json类型点转化为元字典格式
heat_dic = json.loads(heat_dic_json)
# 有一个 MD5 效验
# 6.接收原始数据
ret = hashlib.md5()
with open(os.path.join(file_path,heat_dic['new_file_name']),mode='wb') as f:
total_size = 0
while total_size < heat_dic['file_size']:
every_data = conn.recv(1024)
f.write(every_data)
ret.update(every_data)
file_md5 = ret.hexdigest()
total_size += len(every_data)
if file_md5 != heat_dic['MD5']:
conn.send('文件上传失败!'.encode('utf8'))
os.remove(os.path.join(file_path,heat_dic['new_file_name']))
else:
conn.send('文件上传成功!'.encode('utf8'))
conn.close()
server.close()
socket_server()
# client
import socket
import struct
import json
import os
import hashlib
file_path = os.path.join(os.path.dirname(__file__),'小猪佩奇.py')
def md5_file(path):
ret = hashlib.md5()
with open(path,mode="rb") as f:
while 1:
content = f.read(1024)
if content:
ret.update(content)
else:
return ret.hexdigest()
def socket_client():
client = socket.socket()
client.connect(('127.0.0.11',8888))
# 1. 制作字典形式的报头
head_dic = {
'MD5':md5_file(file_path),
'file_name':os.path.basename(file_path),
'file_size':os.path.getsize(file_path),
'new_file_name':'新小猪佩奇.py'
}
# 2. 利用json将字典报头变成特殊的字符串
head_dic_json = json.dumps(head_dic)
# 3.通过编码将特殊字符串的字典报头 变成bytes类型
head_dic_json_bytes = head_dic_json.encode('utf-8')
#4.获取bytes类型报头的总字节数
head_dic_json_bytes_size = len(head_dic_json_bytes)
# 5.通过struct 将总字节数 转化为固定 4个字节
four_head = struct.pack('i',head_dic_json_bytes_size)
# 6.发送固定4个字节的报头
client.send(four_head)
# 7.发送报头
client.send(head_dic_json_bytes)
# 8.发送数据
'''
循环条件设定:
1. 根据总子节数: file_size: 493701, 每次循环1024个,
2. 每次取数据不为空,即可.
'''
with open(file_path,mode='rb') as f:
while 1:
every_data = f.read(1024)
if every_data:
client.send(every_data)
else:
break
print(client.recv(1024).decode('utf-8'))
client.close()
socket_client()
socketserver实现并发 ( 基于TCP协议 )
#serversocket 实现并发
# server
import socketserver
class MyServer(socketserver.BaseRequestHandler):# 继承的类固定 BaseRequestHandler
def handle(self): # 必须是这个 handle名字 涉及到类的约束,上面继承的类中有handle方法
while 1:
from_client_data = self.request.recv(1024).decode('utf-8') # self.request相当于conn 传输通道
print(from_client_data)
to_client = input(">>>").strip().encode("utf-8")
self.request.send(to_client)
if __name__ == '__main__':
ip_port = ('127.0.0.1',8087)
# socketserver.TCPServer.allow_reuse_address = True # 允许端口重用
server = socketserver.ThreadingTCPServer(ip_port,MyServer)
server.serve_forever() # 对象执行serve_forever方法,开启服务端
# 对 socketserver.ThreadingTCPServer 类实例化对象,将ip地址,端口号以及自己定义的类名传入,并返回一个对象
# 1. 入口点:ThreadingTCPServer()
# client
import socket
client = socket.socket()
client.connect(('127.0.0.1',8087))
while 1:
to_server = input('>>>').strip()
client.send(f'来自fuck的消息: {to_server}'.encode('utf-8'))
from_server_data = client.recv(1024)
print(f'来自服务端的消息:{from_server_data.decode("utf-8")}')
client.close()
基于udp协议的socket ***
-
udp协议: 不可靠,相对来说不安全的协议,面向数据报(无连接)的协议,效率高,速度快
-
语法区别 :
udp_server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
server.recvfrom(1024)
server.sendto
# server
import socket
udp_server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # 基于网络, udp协议的socket
udp_server.bind(('127.0.0.1',8089))
while 1:
from_client_data = udp_server.recvfrom(1024)
# from_client_data 是一个元组 第一个元素是传输数据, 第二个是连接地址
print(f'来自{from_client_data[1]}的消息:{from_client_data[0].decode("utf-8")}')
to_client_data = input(">>").strip().encode('utf-8')
udp_server.sendto(to_client_data,from_client_data[1])
# 依旧还是串行 一对一传输
# client
import socket
udp_client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # 基于网络, udp协议的socket
while 1:
to_server_data = input('>>>')
udp_client.sendto(to_server_data.encode('utf-8'),('127.0.0.1',8089))
from_server_data = udp_client.recvfrom(1024)
print(f"来自{from_server_data[1]}的消息:{from_server_data[0].decode('utf-8')}")