• TCP大文件上传与UDP协议


    一、UCP大文件上传(解决粘包问题)

    ①客户端

    import socket, os, json, struct
    
    client = socket.socket()
    client.connect(('127.0.0.1', 8080))
    # 文件大小
    file_size = os.path.getsize(r'D:Desktopwendang.txt')
    
    # 文件名
    file_name = '计算机五大.txt'
    
    # 然后定义一个字典
    d = {
        'file_name': file_name,
        'file_size': file_size,
        'msg': '成功上传'
    }
    # 定义好字典后,先去转一下json,然后encode
    data_bytes = json.dumps(d).encode('utf-8')
    
    # 制作字典的报头
    header = struct.pack('i', len(data_bytes))
    
    # 发送报头
    client.send(header)
    
    # 发送字典
    client.send(data_bytes)
    
    # 然后发送真实数据:打开文件,一行一行读取出来,一行一行的发送
    with open(r'D:Desktopwendang.txt', 'rb') as f:
        for line in f:
            client.send(line)

    ②服务端

    import socket, json, struct
    
    server = socket.socket()
    server.bind(('127.0.0.1', 8080))
    server.listen(5)
    
    while True:
        conn, addr = server.accept()
        while True:
            try:
                # 先接收报头
                header = conn.recv(4)
    
                # 解析报头,获取字典长度
                header_len = struct.unpack('i', header)[0]
    
                # 接收字典
                header_bytes = conn.recv(header_len)
                header_dic = json.loads(header_bytes.decode('utf_8'))
                print(header_dic)    # 打印字典
    
                # 循环接收文件,存储到本地
                file_size = header_dic.get('file_size')
                file_name = header_dic.get('file_name')
                recv_size = 0
    
                # 文件操作
                with open(file_name, 'wb') as f:
                    while recv_size < file_size:    # 循环接收
                        data = conn.recv(1024)
                        f.write(data)
                        recv_size += len(data)
                print(header_dic.get('msg'))   # 文件上传成功后的提示信息
              
            except ConnectionResetError:
                break
        conn.close()

    二、UDP协议(数据报协议):

    没有双向通道,传输数据不可靠,可能出现丢包现象

    通信速度比较快,发送的数据不会在内存中保留

    1、特性:

    ①UDP协议不存在粘包问题

    ②客户端可以发空,自带数据报头

    ③udp可以实现并发的效果

    ④服务端不存在,也不影响客户端朝服务端发送数据

    2、分析:

    ①UDP叫数据报协议,意味着发消息都带有数据报头

    ②UDP的server不需要就行监听也不需要建立连接

    ③启动服务之后只能被动的等待客户端发消息过来,

      客户端发消息的时候,带上服务端的地址 client.sendto(b'hello', server_addr)

      服务端发消息的时候,带上客户端的地址 server.sendto(msg.upper(), addr)

    3、TCP和UDP

    TCP:类似于打电话,要确定服务端收到

    UDP:类似于发短信,不考虑服务端是否收到

    4、UDP简单使用

    ①服务端

    import socket
    
    server = socket.socket(type=socket.SOCK_DGRAM)
    server.bind(('127.0.0.1', 8080))
    
    msg, addr = server.recvfrom(1024)
    server.sendto(msg.upper(), addr)
    print(msg, addr)

    ②客户端

    import socket
    
    client = socket.socket(type=socket.SOCK_DGRAM)
    server_addr = ('127.0.0.1', 8080)  # 服务端地址,通常写在配置文件中
    
    client.sendto(b'hello', server_addr)
    
    msg, addr = client.recvfrom(1024)
    print(msg, addr)

    5、UDP不存在粘包现象

    UDP不存在粘包现象,是由于UDP发送的时候,没有经过Negal算法优化,不会将多个小包合并一次发送出去。另外,在UDP协议的接收端,采用了链式结构来记录每一个到达的UDP包,这样接收端应用程序一次recv只能从socket接收缓冲区中读出一个数据包。也就是说,发送端send了几次,接收端必须recv几次(无论recv时指定了多大的缓冲区)。

    ①服务端

    import socket
    
    server = socket.socket(type=socket.SOCK_DGRAM)
    server.bind(('127.0.0.1', 8080))
    
    # 验证udp是否粘包:不粘包
    msg, addr = server.recvfrom(1024)
    print(msg)    # b'baby~'
    msg1, addr1 = server.recvfrom(1024)
    print(msg1)   # b'baby~'
    msg2, addr2 = server.recvfrom(1024)
    print(msg2)   # b'baby~'

    ②客户端

    import socket
    
    client = socket.socket(type=socket.SOCK_DGRAM)
    server_addr = ('127.0.0.1', 8080)  # 服务端地址,通常写在配置文件中
    
    
    # 验证udp是否粘包:不粘包
    client.sendto(b'baby~', server_addr)
    client.sendto(b'baby~', server_addr)
    client.sendto(b'baby~', server_addr)

    三、基于UDP实现简易版本的QQ

     ①服务端

    import socket
    
    server = socket.socket(type=socket.SOCK_DGRAM)
    server.bind(('127.0.0.1',8080))
    
    while True:
        msg,addr = server.recvfrom(1024)
        print(msg.decode('utf-8'))
        data = input('>>>:').encode('utf-8')
        server.sendto(data,addr)

    ②客户端

    import socket
    
    client = socket.socket(type=socket.SOCK_DGRAM)
    server_addr = ('127.0.0.1',8080)
    
    while True:
        msg = input('>>>:')
        msg = '客户端1的消息:%s'%msg
        client.sendto(msg.encode('utf-8'),server_addr)
        data,addr = client.recvfrom(1024)
        print(data)

    四、socketserver模块

     1、能够实现并发效果
       并发:看起来像同时运行就能称之位并发
     2、udp在使用的时候,多个客户端要有一些io操作,不然容易卡死

  • 相关阅读:
    VirtualBox 下USB 设备加载的步骤及无法加载的解决办法
    浅析:setsockopt()改善socket网络程序的健壮性
    减小Gcc编译程序的体积
    linux下查看系统进程占用的句柄数
    Linux下高并发socket最大连接数所受的各种限制
    spring-jpa通过自定义sql执行修改碰到的问题
    阿里巴巴Java开发手册中的DO、DTO、BO、AO、VO、POJO定义
    sql select时增加常量列
    CASE WHEN 及 SELECT CASE WHEN的用法
    MYSQL常见运算符和函数
  • 原文地址:https://www.cnblogs.com/zhangguosheng1121/p/10822698.html
Copyright © 2020-2023  润新知