zoukankan      html  css  js  c++  java
  • 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操作,不然容易卡死

  • 相关阅读:
    【转】VS2010中 C++创建DLL图解
    [转]error: 'retainCount' is unavailable: not available in automatic reference counting mode
    [转]关于NSAutoreleasePool' is unavailable: not available in automatic reference counting mode的解决方法
    【转】 Tomcat v7.0 Server at localhost was unable to start within 45
    【转】Server Tomcat v7.0 Server at localhost was unable to start within 45 seconds. If
    【转】SVN管理多个项目版本库
    【转】eclipse安装SVN插件的两种方法
    【转】MYSQL启用日志,和查看日志
    【转】Repository has not been enabled to accept revision propchanges
    【转】SVN库的迁移
  • 原文地址:https://www.cnblogs.com/zhangguosheng1121/p/10822698.html
Copyright © 2011-2022 走看看