封装了简单的网络流操作类 需要的同学可以自行扩展
具体使用的接口解释可以参照官网文档的 python struct API
https://docs.python.org/2/library/struct.html
import struct
from ctypes import create_string_buffer
import binascii as B
"""
protocolStream.py
"""
class ProtocolStreamWriter():
ALLOC_SIZE = 2048
offset = 0
length = 0
content = create_string_buffer(ALLOC_SIZE)
def sendUnsignByte(self,value):
struct.pack_into('!B',self.content,self.offset,value)
self.printtest(value,'!B')
self.offsetMove(1)
def sendShort(self,value):
struct.pack_into('!h',self.content,self.offset,value)
self.printtest(value, '!h')
self.offsetMove(2)
def sendInt(self,value):
struct.pack_into('!i',self.content,self.offset,value)
self.printtest(value, '!i')
self.offsetMove(4)
def sendLong(self, value):
struct.pack_into('!q',self.content,self.offset,value)
self.printtest(value, '!q')
self.offsetMove(8)
def sendString8(self,value):
datas = bytes(value)
length = len(datas)
self.sendUnsignByte(length)
fmt = '!%ds' % (length)
struct.pack_into(fmt, self.content,self.offset,datas)
self.printtest(value, fmt)
self.offsetMove(length)
def sendString16(self,value):
datas = bytes(value)
# contstr = contstr[::-1]
length = len(datas)
self.sendShort(length)
fmt = '!%ds' % (length)
struct.pack_into(fmt, self.content,self.offset,datas)
self.printtest(value, fmt)
self.offsetMove(length)
def sendStructDatas(self, length, value):
needReallocate = False
while(length >= (self.ALLOC_SIZE / 2)):
self.ALLOC_SIZE *=2
needReallocate = True
if(needReallocate):
self.reallocate()
fmt = '!%ds' % (length)
struct.pack_into(fmt,self.content,self.offset,value.raw)
self.printtest(value, fmt)
self.offsetMove(length)
def seek(self,offset):
self.offset = offset
def offsetMove(self, offset):
self.offset += offset
if (self.offset >= self.length):
self.length = self.offset
self.checkReallocate()
def checkReallocate(self):
if (self.length >= (self.ALLOC_SIZE / 2)):
self.ALLOC_SIZE *= 2
self.reallocate()
def reallocate(self):
newContent = create_string_buffer(self.ALLOC_SIZE)
fmt = '!%ds' % (self.length)
struct.pack_into(fmt, newContent, 0, self.content.raw)
self.content = newContent
def printtest(self,value,fmt):
pass
#debug
"""
#size = struct.calcsize(fmt)
#print '#####send start#####'
#print value
#for i in range(self.offset,self.offset + size):
#print B.b2a_hex(self.content.raw[i])
#print '#####send end#####'
"""
"""
ProtoStreamReader
"""
class ProtocolStreamReader():
offset = 0
data = ""
def __init__(self,data):
self.data = data
#unsign
def readUnsignByte(self):
content, = struct.unpack_from('!B',self.data,self.offset)
self.offsetMove(1)
return content
def readShort(self):
content, = struct.unpack_from('!h',self.data,self.offset)
self.offsetMove(2)
return content
def readInt(self):
content, = struct.unpack_from('!i',self.data,self.offset)
self.offsetMove(4)
return content
def readLong(self):
content, = struct.unpack_from('!q',self.data,self.offset)
self.offsetMove(8)
return content
def readString8(self):
len = self.readUnsignByte()
fmt = '!%ds'%(len)
content, = struct.unpack_from(fmt,self.data,self.offset)
self.offsetMove(len)
return content
def readString16(self):
len = self.readShort()
fmt = '!%ds'%(len)
content, = struct.unpack_from(fmt,self.data,self.offset)
self.offsetMove(len)
return content
def offsetMove(self,offset):
self.offset +=offset
######################################################################
socket 使用与连接
以下是演示代码(徒手打码 可能有错)
import socket
import threading
import time
from time import sleep
from protocolStream import *
######################################################################
#message
MSG_LOGIN_REQ = ...
MSG_LOGIN_RESP = ...
class UserInfo():
username =""
uid = 0
...
global running
global userInfo
userInfo = UserInfo()
######################################################################
def sendStart(writer,messageId):
writer.sendInt(0)//length
writer.sendUnsignByte(...)
writer.sendInt(messageId)
....
#write your header
def sendEnd(writer):
writer.seek(0)
writer.sendInt(writer.length - 4)
putSend(writer)
sendQueues = []
def putSend(writer):
length = writer.length
content = create_string_buffer(length)
fmt = '!%ds' % (length)
struct.pack_into(fmt, content, 0, writer.content.raw)
#debug
print repr(content)
sendQueues.append(content)
def sendLogin():
writer = ProtocolStreamWriter()
sendStart(writer,MSG_LOGIN_REQ, REDIR_SERVER_INSTANCE_ID)
#put your userInfo ...
sendEnd(writer)
def readLogin(reader):
print "login success"
def msg_reader_handle(reader):
....
#reader your header
msgId = reader.readInt()
....
#deal your message
if(msgId == MSG_LOGIN_RESP):
readLogin(reader)
.....
def threaded_function(domain,port):
global running
redirect = False
start = time.clock()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.setdefaulttimeout(20)
s.connect((domain, port))
print "connect %s cost %s second" % (domain, time.clock() - start)
while running:
for data in sendQueues:
s.sendall(data)
sendQueues[:] = []
try:
buf = s.recv(4096)
buflen = len(buf)
except Exception,e:
print e
buflen = 0
if not buflen:
break
reader = ProtocolStreamReader(buf)
reallen = reader.readInt()
if (buflen - 4 >= reallen):
msg_reader_handle(reader)
print "socket loop"
sleep(1)
print "scoket close"
def startSocket(domain,port):
global running
running = True
t = threading.Thread(target=threaded_function,args=(domain,port))
t.start()
#test
if __name__ == '__main__':
userInfo.username = "luoyecao"
userInfo.uid = 111111
startSocket("your server domain", your server port)
sendLogin()