网络编程 文件传输 基于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')}")
posted @ 2019-07-18 12:55  樊xs  阅读(390)  评论(0编辑  收藏  举报