zoukankan      html  css  js  c++  java
  • day31——recv工作原理、高大上版解决粘包方式、基于UDP协议的socket通信

    day31

    recv工作原理

    源码解释:
    Receive up to buffersize bytes from the socket.
    接收来自socket缓冲区的字节数据,
    For the optional flags argument, see the Unix manual.
    对于这些设置的参数,可以查看Unix手册。
    When no data is available, block untilatleast one byte is available or until the remote end is closed.
    当缓冲区没有数据可取时,recv会一直处于阻塞状态,直到缓冲区至少有一个字节数据可取,或者远程端关闭。
    When the remote end is closed and all data is read, return the empty string.
    关闭远程端并读取所有数据后,返回空字符串。
    

    高大上版解决粘包方式(自定制报头)

    我们要制作固定的报头

    你现在有两段不固定长度的bytes类型,我们要固定的报头,所以

    • 你获取不固定报头的长度
    • 利用struct模块将不固定的长度转化成固定的字节数4个字节
    • 先发4个字节,再发报头数据,再发总数据
    server
    import socket
    import subprocess
    import struct
    import json
    phone = socket.socket()
    phone.bind(("127.0.0.1",8080))
    phone.listen(3)
    while 1:
        conn, addr = phone.accep()
        print(f"{addr}客户端链接了")
        while 1:
            try:
                from_client_data = conn.recv(1024)
                obj = subprocess.Popen(from_client_data.decode("utf-8"),
                                      shell = True,
                                      stdout = subprocess.PIPE,
                                      stderr = subprocess.PIPE
                                      )
                data = obj.stdout.read() + obj.stderr.read()
                data_len = len(data)
                
                # 1、自定义报头
                head_dic = {
                    "file_name": "test1",
                    "md5": 654654654654,
                    "total_size": data_len
                }
                
                # 2、json形式的报头
                head_dic_json = json.dumps(head_dic)
                
                # 3、bytes形式的报头
                head_dic_json_bytes = head_dic_json.encode("utf-8")
                
                # 4、bytes形式的报头的总字节数
                len_head_dic_json_bytes = len(head_dic_json_bytes)
                
                # 5、把报头的总字节数变成固定的4个字节
                four_head_bytes = struct.pack("i", len_head_dic_json_bytes)
                
                # 6、发送固定的4个字节
                conn.send(four_head_bytes)
                
                # 7、发送bytes形式的报头
                conn.send(head_dic_json_bytes)
                
                # 8、发送总数据
                conn.send(data)
            exctpt Exception:
                print(f"{addr}客户端关闭!")
                break
        conn.close()
    phone.close()                       
    
    client
    import socket
    import struct
    import json
    phone = socket.socket()
    phone.connect(("127.0.0.1", 8080))
    while 1:
        data = input("请输入>>>")
        if not data:
            print("输入内容不为空!")
            continue
        phone.send(data.encode("utf-8"))
        if data.upper() == "Q":
            print("通信关闭")
            break
        
        # 1、获取报头的固定4个字节
        four_head_bytes = phone.recv(4)
        
        # 2、把固定的4个字节变成bytes形式的报头的总字节数
        len_head_dic_json_bytes = struct.unpack("i", four_head_bytes)[0]
        
        # 3、获取到bytes形式的报头
        head_dic_json_bytes = phone.recv(len_head_dic_json_bytes)
        
        # 4、获取json形式的报头
        head_dic_json = head_dic_json_bytes.decode("utf-8")
        
        # 5、获取报头
        dic = json.loads(head_dic_json)
        
        # 6、获取总数据长度
        data_len = dic["total_size"]
        
        # 7、定义一个空字节
        data_deposit = b""
        
        # 8、循环获取总数据
        while len(data_deposit) < data_len:
            data_deposit += phone.recv(1024)
        # 把总数据转成源数据
        print(data_deposit.decode("gbk"))
    phone.close()
    

    基于UDP协议的socket通信

    多人在服务器聊天

    server

    import socket
    server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    server.bind(("127.0.0.1", 9000))
    
    while True:
        conn, addr = server.recvfrom(1024)
        print(f"来自{addr}的消息:{conn.decode('utf-8')}")
    

    client

    import socket
    client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    
    while True:
        data = input(">>>")
        client.sendto(data.encode("utf-8"), ("172.0.0.1", 8080))
    
    服务器与多人聊天

    server

    import socket
    server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    server.bind(("127.0.0.1", 9000))
    
    while True:
        conn, addr = server.recvfrom(1024)
        print(f"来自{addr}的消息:{conn.decode('utf-8')")
        
        data = input(">>>")
        server.sendto(data.encode("utf-8"), addr)
    

    client

    import socket
    client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    
    while True:
        data = input(">>>")
        client.sendto(data.encode("utf-8"), ("127.0.0.1", 9000))
    
        conn, addr = client.recvfrom(1024)
        print(f"来之{addr}的消息:{conn.decode('utf-8')}")
    
  • 相关阅读:
    基础网络技术--学习网络的的道路漫长啊
    华为nova8se和vivoS7e的区别哪个好
    Java.awt实现一个简单的围棋
    HashMap put原理详解(基于jdk1.8)
    Paper Pal:一个中英文论文及其代码大数据搜索平台
    【u116】最短路计数
    【u108】取数游戏
    【u106】3D模型
    【topcoder SRM 652 DIV2 250】ValueOfString
    【u103】绘制二叉树
  • 原文地址:https://www.cnblogs.com/NiceSnake/p/11385871.html
Copyright © 2011-2022 走看看