Twisted TCP编程

使用Twisted进行TCP编程,主要是针对Protocol、Factory、ClientFactory等类进行编程

Protocol子类

针对每个客户端连接,Twisted框架建立一个Protocol子类的实例管理该连接。需要编写该子类,使其能处理3个基本事件响应函数

  • connectionMade():当连接建立时调用
  • dataReceived():当收到客户端数据时调用
  • connectionLost():当连接断开时调用

Factory

Factory子类起到对Protocol类的管理作用,当有新客户端连接时,框架调用Factory.buildProtocol(),使得程序员可以在这里创建Protocol子类的实例

  • buildProtocol:关键函数,创建Protocol子类,Factory子类需要重写该函数
# code:utf8

from typing import Tuple
from twisted.internet.protocol import Protocol, connectionDone,Factory
from twisted.internet.endpoints import TCP4ServerEndpoint
from twisted.python import failure
from twisted.internet import reactor
from datetime import datetime

clients = []

class Spreader(Protocol):
    '''
    class tcp connect
    '''
    def __init__(self,factory):
        '''
        构造函数
        :param factory:
        '''
        self.factory = factory

    def connectionMade(self):
        self.factory.numProtocols = self.factory.numProtocols+1
        str_msg = "欢迎来到Spread Site,你是第%d个客户端\n"%(self.factory.numProtocols)
        self.transport.write(str_msg.encode('utf8'))
        print('new connect:%d'%self.factory.numProtocols)
        clients.append(self)

    def dataReceived(self, data: bytes):
        if data.decode('utf8') == 'close':
            self.transport.loseConnection()
        else:
            print(data.decode('utf8'))
            str_msg = 'hello , i am %s %s'%('server',datetime.now())
            self.transport.write(str_msg.encode('utf8'))

    def connectionLost(self, reason: failure.Failure = connectionDone):
        self.factory.numProtocols = self.factory.numProtocols-1
        clients.remove(self)
        print('lost connect : %d '%self.factory.numProtocols)


class SpreadFactory(Factory):
    def __init__(self):
        self.numProtocols = 0

    def buildProtocol(self, addr: Tuple[str, int]) -> "Protocol":
        '''
        创建Protocol 子类
        :param addr:
        :return:
        '''
        return Spreader(self)

endpoint = TCP4ServerEndpoint(reactor,8007)
endpoint.listen(SpreadFactory())
reactor.run()

ClientFactory

比Factory多了三个函数

  • startedConnecting():开始连接的时候调用
  • clientConnectionLost():连接断开时调用
  • clientConnectionFailed():连接失败时调用

客户端使用twisted.internet.reactor.connectTCP()连接指定的服务器

# code:utf8
import sys
import threading
import time
from datetime import datetime
from typing import Tuple

from twisted.internet import reactor
from twisted.internet.protocol import Protocol, ClientFactory, connectionDone
from twisted.python import failure


class Echo(Protocol):
    def __init__(self):
        self.connected = False

    def connectionLost(self, reason: failure.Failure = connectionDone):
        self.connected=False

    def connectionMade(self):
        self.connected=True

    def dataReceived(self, data: bytes):
        print(data.decode('utf8'))
        
    def close(self):
        '''
        关闭连接
        :return:
        '''
        self.transport.loseConnection()
        
class EchoClientFactory(ClientFactory):
    def __init__(self):
        self.protocol = None

    def startedConnecting(self, connector):
        '''
        事件:开始连接的时候调用
        :param connector: 
        :return: 
        '''
        print('Started to connect.')

    def buildProtocol(self, addr: Tuple[str, int]) -> "Protocol":
        '''
        创建客户端Protocol子类
        :param addr: 
        :return: 
        '''
        print('Connected')
        self.protocol = Echo()
        return self.protocol

    def clientConnectionFailed(self, connector, reason):
        '''
        事件:连接失败时调用
        :param connector: 
        :param reason: 
        :return: 
        '''
        print('Connected failed. Reason :',reason)

    def clientConnectionLost(self, connector, reason):
        '''
        事件:连接断开时调用
        :param connector: 
        :param reason: 
        :return: 
        '''
        print('Lost Connection . Reason :',reason)

b_stop = False

def routeine(factory:EchoClientFactory):
    while not b_stop:
        if factory.protocol and factory.protocol.connected:
            str_msg = 'hello , i am %s %s'%(sys.argv[0],datetime.now())
            factory.protocol.transport.write(str_msg.encode('utf8'))
            time.sleep(5)

host = '127.0.0.1'
port=8007
factory = EchoClientFactory()
reactor.connectTCP(host,port,factory)
threading.Thread(target=routeine,args=(factory,)).start()
reactor.run()
b_stop = True

客户端与服务器的编程模式一致

TCP Server 示例

以下代码可以不用定义Factory子类,不用TCP4ServerEndpoint启动服务

factory  = protocol.Factory()
factory.protocol = TSServerProtocol
reactor.listenTCP(PORT,factory)
reactor.run()

Protocol 子类只需要实现connectionMade、connectionLost、dataReceived事件定义和必要的自定义函数即可

# coding:utf8

import zlib
from tools.sys_log import logger
from twisted.internet import protocol,reactor

PORT = 8006

class TSServerProtocol(protocol.Protocol):
    '''
    server handler
    '''
    __buffer_cache = None
    
    def connectionMade(self):
        '''
        client first connected
        '''
        client_info = self.transport.getPeer() # 获取客户端的IP和端口
        # ip = client_info.host # str
        # port = client_inof.port # int
        logger.info(f'connect from {client_info}')
    
    def dataReceived(self, data: bytes):
        '''
        receive cilent data
        '''
        if self.__buffer_cache == None:
           self.__buffer_cache = data
        else:
           self.__buffer_cache+=data
        # 解析数据,对数进行处理
        print(self.__buffer_cache.decode('utf8'))
        self.__buffer_cache = None

    def connectionLost(self, reason):
        '''
        client close
        '''
        client_info = self.transport.getPeer()
        logger.info(f'lost connection from {client_info}:{reason}')
        self.__buffer_cache = None
        return
    
    def writeBuff(self,data:bytes):
        """_summary_
            send buff to client
        Args:
            data (bytes): buff
        """        
        self.transport.write(data)
        

if __name__ =='__main__':
    logger.info('server start ......')
    factory  = protocol.Factory()
    factory.protocol = TSServerProtocol
    reactor.listenTCP(PORT,factory)
    reactor.run()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值