zoukankan      html  css  js  c++  java
  • 自定制报头 UDP协议下的socket通信

    自定制报头

    1.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 untilat least 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.
    	关闭远程端并读取所有数据后,返回空字符串。
    

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

    # server服务端
    import socket
    import struct
    import json
    import subprocess
    
    phone = socket.socket()
    
    phone.bind(("127.0.0.1", 8848))
    phone.listen()
    
    while 1:
        conn, addr = phone.accept()
        print(conn, addr)
        while 1:
            try:
                from_client_data = conn.recv(1024)
                # print(f"{from_client_data.strip().decode('utf-8')}")
                obj = subprocess.Popen(from_client_data.decode("utf-8"),
                                       shell=True,
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.PIPE,
                                       )
                to_client_data = obj.stdout.read() + obj.stderr.read()
                total_size = len(to_client_data)
    
                head_dic = {"file_name": "test", "md5": 646846, "total_size": total_size}
    			# 报头字典
                
                head_dic_json_bytes = json.dumps(head_dic).encode("utf-8")
                # 报头字典str然后转字节
    
                len_head_dic_json_bytes = len(head_dic_json_bytes)
    			# 报头字典str字节数
                
                four_head_bytes = struct.pack("i", len_head_dic_json_bytes)
                # 制作报头字典字节int的固定字节数
    
                conn.send(four_head_bytes)
                # 发送报头字典字节int的固定字节数
    
                conn.send(head_dic_json_bytes)
    			# 发送报头字典
                
                conn.send(to_client_data)
                # 发送总数据
    
            except ConnectionResetError:
                print("客户端中断")
                break
        conn.close()
    phone.close()
    
    # client客户端
    import socket
    import struct
    import json
    
    phone = socket.socket()
    
    phone.connect(("127.0.0.1", 8848))
    
    while 1:
        to_server_data = input(">>>").strip().encode("utf-8")
        if not to_server_data:
            print("输出不能为空")
        phone.send(to_server_data)
        if to_server_data.upper() == b'Q':
            print("客户端退出")
    
        four_head_bytes = phone.recv(4)
        # 接收报头字典的固定字节
    
        len_head_dic_json_bytes = struct.unpack("i", four_head_bytes)[0]
        # 报头字典的字节数
    
        head_dic_json_bytes = phone.recv(len_head_dic_json_bytes)
        # 接收报头字典字节
    
        head_dic = json.loads(head_dic_json_bytes.decode("utf-8"))
        # 报头字典
    
        recv_size = 0
        from_server_data = b''
        while recv_size < head_dic["total_size"]:
            recv_data = phone.recv(1024)
            from_server_data += recv_data
            recv_size += len(recv_data)
    
        print(from_server_data.decode("gbk"))
    

    3.基于UDP协议的socket通信

    ​ 先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),recvform接收消息,这个消息有两项,消息内容和对方客户端的地址,然后回复消息时也要带着你收到的这个客户端的地址,发送回去,最后关闭连接,一次交互结束

    ​ 发消息必须带着自己的地址,这就是UDP不一样的地方,不需要建立连接,但是要带着自己的地址给服务端,否则服务端无法判断是谁给我发的消息,并且不知道该把消息回复到什么地方,因为我们之间没有建立连接通道

    # server端
    import socket
    while 1:
            phone = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            phone.bind(("127.0.0.1", 8848))
    
            from_msg, addr = phone.recvfrom(1024)
            print(from_msg.decode("utf-8"), addr)
    
            to_msg = input(">>>").strip().encode("utf-8")
            phone.sendto(to_msg, addr)
    phone.close()
    
    # client端
    import socket
    
    phone = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    ip_client = ("127.0.0.1", 8848)
    while 1:
            to_msg = input(">>>").strip().encode("utf-8")
            phone.sendto(to_msg, ip_client)
            if to_msg.upper() == b'Q' :
                print("退出成功")
                break
    
            from_msg, addr = phone.recvfrom(1024)
            print(from_msg.decode("utf-8"), addr)
    phone.close()
    
  • 相关阅读:
    unity中制作模拟第一人称视角下的指南针
    unity3D 中的C#脚本一个类调用另一类中简单方法
    unity中UI的屏幕自适应代码
    unity中导入插件时报错处理办法
    Unity3D在C#编程中的一些命名空间的引用及说明
    Unity中物体碰撞后去掉相互之间的反弹力
    unity3D打包发布Apk详细步骤
    unity3D开发的程序发布到Android平台上进行运行测试的详细步骤
    JAVA的环境变量配置(方式二)
    Java中的 JDK下载和环境配置(方式一)
  • 原文地址:https://www.cnblogs.com/beichen123/p/11366218.html
Copyright © 2011-2022 走看看