twisted 以及相关源码

官方文档不怎么友好..哈哈哈

自己写了个

总体按照:https://twistedmatrix.com/documents/current/core/howto/servers.html 来写

twisted总体就是一个循环. 下面我会按照 socket编程 的习惯来说明

第一个例子: 里面有2个类

说简单说明一下:

1. Protocol 类, 内部封装了一个  transport 对象, 这个 transport 内部又封装了 socket 对象.

    transort   ->    twisted.internet.tcp.Server .

    综上来说你可以把protocol.transort 认为是一个socket对象, 如果要发送数据可以使用  transport.write

2.  Factory类. 用于创建 一个个 Protocol 对象的,即创建一个个socket对象.(其实不是),下面有源码解释

3. 下面的例子都可以使用telnet 来充当客户端

其他的说明在下面代码中

from twisted.internet.selectreactor import  SelectReactor
from twisted.internet.protocol import  Protocol,Factory
import  time

#这一行可以省略. 可以直接 from twisted.internet import reactor
reactor = SelectReactor()

#Protocol  相当于一个个 socket
class Echo(Protocol):

    # addr 由工厂传递对方 ip 地址
    def __init__(self,addr):
        self.addr = addr
        print('echo init ,peer addr :' , addr)

    
    #重写的函数, 数据一旦到达
    def dataReceived(self, data):
        print('datarecvd :', data)
        self.transport.write(data)

    #socket 一旦 被监听套接字 accept 后
    def connectionMade(self):
        print('connectionMade ' )
        self.transport.write(b'connectionMade')

    #对端关闭
    def connectionLost(self, reason):
        print('connectlost')





#工厂将创建一个个Protocol对象, 你可以把Protocol 对象当作socket来对象
class fa(Factory):
    protocol = Echo #buildProtocol 根据这个类属性来创建protocol
    

    #重写了buildProtocol ,默认源码中并没有传递 addr .其他都一样, 每一次有客户端连接都将调用
    def buildProtocol(self, addr):
        print('buildProtocol : ', addr)
        p = self.protocol(addr)
        p.factory = self
        return p


#listenTcp 先将创建监听套接字,然后用于监听18900端口 ,具体可以看之后的 c 代码解释
reactor.listenTCP(18900,fa(),100)
reactor.run()

#工厂, 即创建一个个 protocol  , 其实socket并不是他创建的,只是用他来管理一个个protocol对象
'''
    源码: 只留了重要的

            #这个clients 内部是真正的socket对象
            clients = _accept(bufferingLogger, range(numAccepts),self.socket,_reservedFD)

            #获取host
             host = socket.getnameinfo(addr, socket.NI_NUMERICHOST |         socket.NI_NUMERICSERV)

            #获取addr
             addr = tuple([host[0]] + list(addr[1:]))
            
            #self.factory 是我们传递进去的工厂, 用来创建一个个protocol对象
             protocol = self.factory.buildProtocol(self._buildAddr(addr))
            
            #transport 是将存放accept返回的socket对象
            transport = self.transport(skt, protocol, addr, self, s, self.reactor)

            #最后把transport存放在protocol 中
            protocol.makeConnection(transport)
'''

一般编写服务器时 (用c来解释):

    int listenfd =  socket(AF_INET, SOCK_STREAM,0) # 创建套接字

    #这部分如果看不懂可忽略
    struct sockaddr_in serv_addr;
    memset(&serv_addr,0,socklen);  
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(12345);
    serv_addr.sin_family = AF_INET;
    #这部分如果看不懂可忽略


     #绑定到本地ip port
    if(bind(listensock,(SA*)&serv_addr,sizeof(serv_addr)) < 0){
        perror("bind");
        return 0;
    }
 
    #转成监听套接字
    if(listen(listensock,BACKLOG) < 0){
        perror("listen");
        return 0;
    }


    #以上部分可以全部忽略, 只看下面的
    while(1){

        #获取socket
        int client_sock = accept(listenfd , ... ) 

        #在twisted中在此将创建一个个protocol,内部存放transport ,transport内部存放socket
        protocol = factory.buildProtocol(... )

        #创建transport对象内部存放 client_sock
        trans = transport( client_sock , .... )
        
        #把transport存放在protocol中
        protocol.makeConnection(transport)

    }

 

 

第2个例子:

在上面的例子 直接继承Protocol 或许不太好用,接收到的都是一个个字符

下面改成  LineReceiver ,他也继承自Protocol ,所以你不用担心:

只改了Echo

from twisted.internet.selectreactor import  SelectReactor
from twisted.internet.protocol import  Protocol,Factory

from twisted.internet.endpoints import TCP4ServerEndpoint
from twisted.protocols.basic import LineReceiver
import  time
reactor = SelectReactor()
from  twisted.internet.tcp import Server

class Echo(LineReceiver):
    def __init__(self,addr):
        self.addr = addr
        print('echo init ,  peer addr:', addr)


    #唯一不一样的地方. dataReceived 在LineReceiver自有实现,我们就别去改了
    #重写这个函数,这个函数将返回一行行数据 ,根据\r\n来分割
    def lineReceived(self, line):
        print('lineReceived :' , line)
    
        #发送回去
        self.sendLine(b'echo' + line)
        #发回去后立刻断开连接
        self.transport.loseConnection()


    def connectionMade(self):
        print('connectionMade :' , type(self.transport), self.transport )
        self.transport.write(b'connectionMade')

    def connectionLost(self, reason):
        print('connectlost')

class fa(Factory):
    protocol = Echo

    def buildProtocol(self, addr):
        print('buildProtocol : ', addr)
        p = self.protocol(addr)
        p.factory = self
        return p


reactor.listenTCP(18900,fa(),100)
reactor.run()

 

第3个例子: 客户端 , 基于上面的服务器 , 除了一个类变了其他都没变

 

from twisted.internet.selectreactor import SelectReactor
from twisted.internet.protocol import  Protocol,ClientFactory,ReconnectingClientFactory
from twisted.internet.tcp import Connector


#还是没变, 把他看成与服务器通信的socket即可
class Echo(Protocol):
    def __init__(self,addr):
        self.addr = addr
        print('serv addr:', addr)

    def dataReceived(self, data):
        print('from serv:', data)
    def connectionMade(self):
        print('connectionMade :' , type(self.transport), self.transport )
        self.transport.write(b'Client connectionMade\r\n')

    def connectionLost(self, reason):
        print('client connectlost :' , reason)



#这里继承了ClientFactory , ClientFactory 继承了Factory ,只是多了些函数罢了
class ClientFa(ClientFactory):
    protocol = Echo #创建协议(socket)

    #开始连接的时候
    def startedConnecting(self, connector:Connector):
        print('startedConnecting , ' ,connector )
        connector.connect()

    #连接失败
    def clientConnectionFailed(self, connector, reason):
        print('clientConnectionFailed' , connector ,reason)
    
    #连接断开
    def clientConnectionLost(self, connector, reason):
        print('clientConnectionLost' , connector, reason)

    #创建protocol
    def buildProtocol(self, addr):
        p = self.protocol(addr)
        p.fa
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值