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')}")
    
  • 相关阅读:
    2018年奇虎360春招笔试题--玫瑰花
    MaxPooling的作用
    网易笔试编程题:被3整除
    网易笔试编程题:牛牛找工作
    剑指offer 第十二天
    算法题:合并N个长度为L的有序数组为一个有序数组(JAVA实现)
    十分钟看懂神经网络反向传输算法
    十大经典排序算法最强总结(含JAVA代码实现)
    记服务器中招挖矿病毒排查过程(解决方案篇)
    spring 事件监听同时支持同步事件及异步事件
  • 原文地址:https://www.cnblogs.com/NiceSnake/p/11385871.html
Copyright © 2011-2022 走看看