【3】python3 socket传输protobuf数据

一、通讯协议
在这里插入图片描述
如上图,采用 datalength+databytes 的自定义长度的协议,其中:
datalength:紧跟其后的databytes的数据长度(不包含自身长度),占4字节
databytes:protobuf 3.0协议数据序列化后的数据内容,长度不限
二 客户端和服务器端代码,接着我的第二篇文章,如下图,注意圈起来的地方
【3】python3 socket传输protobuf数据_第1张图片
客户端代码:ClientProtoTest.py

from socket import *
import google.protobuf
import TransportMessage_pb2
import WeChatOnlineNoticeMessage_pb2
import traceback
import google.protobuf.any_pb2
#from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2
Id = 0

def HearBeatReq_bytes():
    print('心跳包数据...')
    global Id
    Id+=1
    transportMessage = TransportMessage_pb2.TransportMessage()#注意括号不要掉了,
    transportMessage.MsgType = 1010
    transportMessage.Id = Id
    transportMessage.AccessToken ="ac897dss"
    return transportMessage.SerializeToString()

def OnlineNotice_bytes():
    print('上线通知...')
    global Id
    Id+=1
    transportMessage = TransportMessage_pb2.TransportMessage()#注意括号不要掉了,
    transportMessage.MsgType = 1020
    transportMessage.Id = Id
    transportMessage.AccessToken ="ac897dss"

    weChatOnlineNotice = WeChatOnlineNoticeMessage_pb2.WeChatOnlineNoticeMessage()
    weChatOnlineNotice.WeChatId = "wxid_123456789"
    weChatOnlineNotice.WeChatNo = "qdj_cancle"
    weChatOnlineNotice.WeChatNick = "昵称001"
    weChatOnlineNotice.Gender = 0
    weChatOnlineNotice.Country = "中国"
    
    transportMessage.Content.Pack(weChatOnlineNotice)

    return transportMessage.SerializeToString()

HOST = '192.168.0.100'
PORT = 11087
BUFSIZ =1024
ADDR = (HOST,PORT)

tcpCliSock = socket(AF_INET,SOCK_STREAM)
tcpCliSock.connect(ADDR)

while True:
    
    data1 = input('发送数据[0].退出;[1].心跳包;[2].上线通知>')
    print(data1)
    if data1=='0':
        break
    if data1 =='1':
        hearBeat_data = HearBeatReq_bytes()
        byte_data = hearBeat_data
        byte_head = (len(byte_data)).to_bytes(4, byteorder='big')
        tcpCliSock.send(byte_head)
        tcpCliSock.send(byte_data)
    if data1 =='2':
        onlineNotice_bytes = OnlineNotice_bytes()
        byte_data = onlineNotice_bytes
        byte_head = (len(byte_data)).to_bytes(4, byteorder='big')
        tcpCliSock.send(byte_head)
        tcpCliSock.send(byte_data)

tcpCliSock.close()

服务器端代码:ServerProtoTest.py

import socket
import google.protobuf
import google.protobuf.any_pb2
import TransportMessage_pb2
import WeChatOnlineNoticeMessage_pb2

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
HostPort = ('192.168.0.100',11087)
s.bind(HostPort)  #绑定地址端口
s.listen(5)  #监听最多5个连接请求
while True:
    print('server socket waiting...')
    obj,addr = s.accept()  #阻塞等待链接
    print('socket object:',obj)
    print('client info:',addr)
    while True:
        Head_data = obj.recv(4)  #接收数据头 4个字节,
        data_len = int.from_bytes(Head_data, byteorder='big')
        
        protobufdata = obj.recv(data_len)
        
        tmessage = TransportMessage_pb2.TransportMessage()
        tmessage.ParseFromString(protobufdata)
        i_id = tmessage.Id
        i_msgtype = tmessage.MsgType
        print('id:',i_id,'msgType:',i_msgtype)
        if i_msgtype==0:
            print('异常')
            break
        if i_msgtype==1010:
            print('服务器接收到心跳包...')
        if i_msgtype == 1020:
            print('服务器接收到上线通知...')
            online = WeChatOnlineNoticeMessage_pb2.WeChatOnlineNoticeMessage()
            tmessage.Content.Unpack(online)
            print('WeChatNo:'+online.WeChatNo,'WeChatId:'+online.WeChatId,'WeChatNick:'+online.WeChatNick)

三 运行结果演示:
【3】python3 socket传输protobuf数据_第2张图片
总结:protobuf数据最终需要通过SerializeToString()函数转化,通过socket.send函数发送出去,服务器端接收到的数据通过ParseFromString()函数转化成protobuf数据
上一篇:【2】python protobuf泛型类Any使用
下一篇:【4】python3 socket线程处理protobuf数据

你可能感兴趣的:(python,python,socket,protobuf)