一.接着上一篇文章代码,里面添加线程(三种线程方法见代码中注释部分)代码中引用的这两个文件(import TransportMessage_pb2
import WeChatOnlineNoticeMessage_pb2)是处理protobuf数据的,在我的第二篇文章中有介绍。
服务器端代码:ServerProtoTest.py
import socket
import time
import google.protobuf
import google.protobuf.any_pb2
import TransportMessage_pb2
import WeChatOnlineNoticeMessage_pb2
import threading
import gevent
from gevent import socket,monkey
monkey.patch_all()
import socketserver
class Myserver(socketserver.BaseRequestHandler):
def handle(self):
conn = self.request
Thread_recv(conn)
def Thread_recv(socket_Server):
try:
while True:
Head_data = socket_Server.recv(4) #接收数据头 4个字节,
data_len = int.from_bytes(Head_data, byteorder='big')
protobufdata = socket_Server.recv(data_len)
tmessage = TransportMessage_pb2.TransportMessage()
tmessage.ParseFromString(protobufdata)
i_id = tmessage.Id
i_msgtype = tmessage.MsgType
now_time = time.strftime('%Y-%m-%d %H:%M:%S')
print(now_time,' id:',i_id,'msgType:',i_msgtype)
if i_msgtype==0:
print('异常')
break
if i_msgtype==1010:
print(now_time,' 服务器接收到心跳包...')
if i_msgtype == 1020:
print(now_time,' 服务器接收到上线通知...')
#有上线通知,将好友信息和socket_Server套接字存放在buf中,
#这样可以将好友A的信息转发给好友B,做成及时聊天工具
#有下线通知,将好友信息和socket_Server套接字从buf中去掉
#服务器端功能就是收集上线和下线通知,转发聊天消息
online = WeChatOnlineNoticeMessage_pb2.WeChatOnlineNoticeMessage()
tmessage.Content.Unpack(online)
print(now_time,' WeChatNo:'+online.WeChatNo,'WeChatId:'+online.WeChatId,'WeChatNick:'+online.WeChatNick)
except expression as identifier:
print('Thread_recv 异常...')
finally:
socket_Server.close()
if __name__ == "__main__":
#方法3
server = socketserver.ThreadingTCPServer(('192.168.0.100',11087),Myserver)
server.serve_forever()
"""s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
HostPort = ('192.168.0.100',11087)
s.bind(HostPort) #绑定地址端口
s.listen(100) #监听最多100个连接请求
while True:
print('server socket waiting...')
obj,addr = s.accept() #阻塞等待链接
print('socket object:',obj)
print('client info:',addr)
#方法1
#t_recv = threading.Thread(target=Thread_recv,args=(obj,))
#t_recv.start()
#方法2
gevent.spawn(Thread_recv,obj)"""
客户端代码: ClientProtoTest.py
from socket import *
import google.protobuf
import TransportMessage_pb2
import WeChatOnlineNoticeMessage_pb2
import traceback
import google.protobuf.any_pb2
import threading
import time
Id = 0
def HearBeatReq_bytes():
global Id
Id+=1
transportMessage = TransportMessage_pb2.TransportMessage()#注意括号不要掉了,
transportMessage.MsgType = 1010
transportMessage.Id = Id
transportMessage.AccessToken ="ac897dss"
print('心跳包数据...Id=',Id)
return transportMessage.SerializeToString()
def OnlineNotice_bytes():
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 = "中国"
print('上线通知...Id=',Id)
transportMessage.Content.Pack(weChatOnlineNotice)
return transportMessage.SerializeToString()
def thread_HearBeat(tcpCliSock):
while True:
time.sleep(10)
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)
print('10秒定时发送心跳包...\r\n发送数据[0].退出;[1].心跳包;[2].上线通知>')
if __name__ == "__main__":
HOST = '192.168.0.100'
PORT = 11087
BUFSIZ =1024
ADDR = (HOST,PORT)
tcpCliSock = socket(AF_INET,SOCK_STREAM)
tcpCliSock.connect(ADDR)
t_hearBeat = threading.Thread(target=thread_HearBeat,args=(tcpCliSock,))
t_hearBeat.start() #启动心跳线程
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()
二. 运行结果:
一个服务器端,两个客户端运行的结果
总结:线程threading.Thread函数的用法,服务器端有三种线程方法可以解决并发问题。
上一篇:【3】python3 socket传输protobuf数据]
下一篇:【5】python和android之间socket传输protobuf数据]