在上一篇博客中实现了一个简单的socket分发消息的例子,server端只用来分发消息,client只用来收取消息。出于接受消息的需要,将之前的代码丰富优化,补充成为四个类:
1, SendServer:发消息的server
2, RecvClient:收消息的client
3, RecvServer:收消息的server
4,SendClient:发消息的client
12 和34配对使用。
并且,之前代码里由于一个接受client的sleep会导致发送server的等待,在此也进行了修改。多个socket的调用使用select模型。
#!/usr/bin/env python
#coding = utf-8
'''
Author: Yang XU
E-mail: xuy1202@gmail.com
'''
import os
import time
import socket
import threading
from random import choice
import sys
import traceback
import select
import comm
DEBUG = os.environ.get('DEBUG', False)
SPLITER = '\n'
SPLITER_SUB = '<\\n>'
class SendServer(threading.Thread):
def __init__(self, address):
self.address = address
self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._sock.bind(self.address)
self._sock.listen(5)
self.clients = {}
self.SPLITER = SPLITER
self.SPLITER_SUB = SPLITER_SUB
self.over = False
self.DEBUG = DEBUG
if self.DEBUG:
self.logInterval = 600
self.timer = comm.RotateTimer(self.logInterval)
self.msgCount = 0
super(SendServer, self).__init__()
def stop(self):
self.over = True
def run(self):
while not self.over:
try:
client, addr = self._sock.accept()
self.clients[client] = addr
except BaseException, e:
sys.stderr.write(str(e))
sys.stderr.write(str(traceback.format_exc()))
else:
sys.stdout.write('CrazyDoggy SendServer Stopped.')
def send(self, msg):
msg = str(msg).replace(self.SPLITER, self.SPLITER_SUB)
while not self.over:
if self.clients:
_socket = None
try:
socket_list = self.clients.keys()
rl, wl, el = select.select([], socket_list, [], 1)
if not wl: continue
_socket = choice(wl)
_socket.send(msg+self.SPLITER)
if self.DEBUG:
self.msgCount += 1
if not self.timer(): return
sys.stdout.write(
'In the past %s seconds, messages been sent: %s'%(
self.logInterval, self.msgCount
)
)
self.msgCount = 0
return True
except BaseException, e:
sys.stderr.write(str(e))
sys.stderr.write(str(traceback.format_exc()))
if DEBUG:
sys.stdout.write('SendServer: Doggy %s Down.'%str(self.clients.get(_socket)))
self.clients.pop(_socket, None)
else:
time.sleep(3)
sys.stdout.write('No Messenger Doggy OR Doggy Busy.')
else:
sys.stdout.write('CrazyDoggy SendServer Stopped.')
def serve_forever(self):
self.run()
class RecvClient(threading.Thread):
def __init__(self, address):
self.buffer = []
self.address = address
self.SPLITER = SPLITER
self.SPLITER_SUB = SPLITER_SUB
self.last_rem = ''
self.sleep = 0.0001
self.over = False
self.DEBUG = DEBUG
super(RecvClient, self).__init__()
def stop(self):
self.over = True
def get(self, num=1000):
_return = self.buffer[:num]
self.buffer = self.buffer[num:]
return _return
def slowdown(self, sleep=0.01):
self.sleep += sleep
def speedup(self):
self.sleep = 0.0001
def init_socket(self):
while not self.over:
try:
self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._socket.connect(self.address)
return
except BaseException, e:
sys.stderr.write(str(e))
sys.stderr.write(str(traceback.format_exc()))
time.sleep(10)
else:
sys.stdout.write('CrazyDoggy RecvClient Stopped.')
def run(self):
self.init_socket()
while not self.over:
try:
data = self._socket.recv(1024)
if self.last_rem:
data = self.last_rem + data
d_list = data.split(self.SPLITER)
d_list, rem = d_list[:-1], d_list[-1]
d_list = [s.replace(self.SPLITER_SUB, self.SPLITER) for s in d_list]
self.last_rem = rem
self.buffer.extend(d_list)
time.sleep(self.sleep)
length = len(self.buffer)
if length < 1000:
self.speedup()
elif length > 10000:
self.slowdown()
if self.DEBUG:
sys.stdout.write(
'[Debug] buffer size: %s, sleep: %s'%(
str(length), str(self.sleep)
)
)
except BaseException, e:
sys.stderr.write(str(e))
sys.stderr.write(str(traceback.format_exc()))
self.init_socket()
else:
sys.stdout.write('CrazyDoggy RecvClient Stopped.')
def serve_forever(self):
self.run()
class RecvServer(threading.Thread):
def __init__(self, address):
self.address = address
self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._sock.bind(self.address)
self._sock.listen(5)
self.clients = {}
self.buffer = []
self.SPLITER = SPLITER
self.SPLITER_SUB = SPLITER_SUB
self.over = False
if DEBUG:
self.logInterval = 600
self.timer = comm.RotateTimer(self.logInterval)
self.msgCount = 0
super(RecvServer, self).__init__()
def stop(self):
self.over = True
def get(self, num=1000):
_return = self.buffer[:num]
self.buffer = self.buffer[num:]
return _return
def run(self):
threading.Thread(target=self.recv).start()
while not self.over:
try:
client, addr = self._sock.accept()
self.clients[client] = ['', addr]
except BaseException, e:
sys.stderr.write(str(e))
sys.stderr.write(str(traceback.format_exc()))
else:
sys.stdout.write('CrazyDoggy RecvServer Stopped.')
def recv(self):
while not self.over:
try:
if self.clients:
socket_list = self.clients.keys()
rl, wl, el = select.select(socket_list, [], [], 1)
for socket in rl:
try:
data = socket.recv(4096)
rem = self.clients[socket][0]
data = rem + data
d_list = data.split(self.SPLITER)
d_list, rem = d_list[:-1], d_list[-1]
d_list = [s.replace(self.SPLITER_SUB, self.SPLITER) for s in d_list]
self.buffer.extend(d_list)
self.clients[socket][0] = rem
if DEBUG:
length = len(d_list)
self.msgCount += length
if not self.timer(): continue
sys.stdout.write(
'In the past %s seconds, messages been received: %s'%(
self.logInterval, self.msgCount
)
)
self.msgCount = 0
except BaseException, e:
sys.stderr.write(str(e))
sys.stderr.write(str(traceback.format_exc()))
sys.stdout.write('Doggy %s Down.'%str(self.clients[socket][1]))
self.clients.pop(socket, None)
else:
time.sleep(3)
sys.stdout.write('No Messenger Doggy OR Doggy Busy.')
except BaseException, e:
sys.stderr.write(str(e))
sys.stderr.write(str(traceback.format_exc()))
else:
sys.stdout.write('CrazyDoggy RecvServer Stopped.')
def serve_forever(self):
self.run()
class SendClient(threading.Thread):
def __init__(self, address):
self.buffer = []
self.address = address
self.SPLITER = SPLITER
self.SPLITER_SUB = SPLITER_SUB
self.last_rem = ''
self.sleep = 0.1
self.over = False
self.DEBUG = DEBUG
self._socket = None
#self.init_socket()
super(SendClient, self).__init__()
def stop(self):
self.over = True
def init_socket(self):
while not self.over:
try:
self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._socket.connect(self.address)
return
except BaseException, e:
sys.stderr.write(str(e))
sys.stderr.write(str(traceback.format_exc()))
time.sleep(10)
else:
sys.stdout.write('CrazyDoggy SendClient Stopped.')
def send(self, msg):
if not self._socket:
self.init_socket()
while not self.over:
try:
msg = str(msg).replace(self.SPLITER, self.SPLITER_SUB)
self._socket.send(msg+self.SPLITER)
return True
except BaseException, e:
sys.stderr.write(str(e))
sys.stderr.write(str(traceback.format_exc()))
self.init_socket()
else:
sys.stdout.write('CrazyDoggy SendClient Stopped.')
def run(self):
pass
def serve_forever(self):
pass
if __name__ == '__main__':
def _test_SendServer_RecvClient():
global DEBUG
DEBUG = True
S = SendServer(('0.0.0.0', 9999))
S.serve_forever()
DEBUG = False
C = RecvClient(('127.0.0.1', 9999))
C.serve_forever()
count = 0
while 1:
# supply
S.send('mmmmmmmmmmmmmmmmmmmmmmmm_%s'%count)
count += 1
# consume
if count % 52000 == 0:
C.buffer = []
def _test_RecvServer_SendClient():
global DEBUG
DEBUG = True
S = RecvServer(('0.0.0.0', 9999))
S.serve_forever()
C = SendClient(('127.0.0.1', 9999))
C.serve_forever()
count = 0
while 1:
C.send('mmmmmmmmmmmmmmmmmmmmmmmm_%s'%count)
count += 1
#_test_SendServer_RecvClient()
_test_RecvServer_SendClient()
其中,comm模块和上一篇的一样,只用于计时功能。