python socket分发消息例子(续)

在前一篇文章的基础上,本文详细介绍了如何改进Python socket实现,包括新增SendServer(发送消息服务器)、RecvClient(接收消息客户端)、RecvServer(接收消息服务器)和SendClient(发送消息客户端)四个类。设计中,SendServer与RecvClient配合,而RecvServer则与SendClient配合使用,解决了原先代码中因接收客户端导致发送服务器等待的问题,采用select模型实现多个socket的并发处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在上一篇博客中实现了一个简单的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模块和上一篇的一样,只用于计时功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值