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')}")
    
  • 相关阅读:
    paper:synthesizable finit state machine design techniques using the new systemverilog 3.0 enhancements之output encoded style with registered outputs(Good style)
    软测(一)
    package.json
    邬江兴:网络安全“再平衡战略”抓手--拟态防御
    什么是DDOS攻击?怎么防御?
    什么是gitlab CI ?CI代表什么?
    结构体字节对齐(转)
    MySQL 及 SQL 注入与防范方法
    HDU 4704 Sum (费马小定理)
    HDU 4704 Sum (费马小定理)
  • 原文地址:https://www.cnblogs.com/NiceSnake/p/11385871.html
Copyright © 2011-2022 走看看