Python Twisted框架中socket通讯

转载自:http://www.cnblogs.com/sevenyuan/archive/2010/11/18/1880681.html

第一部分:

Twisted使用了更多的基于事件的方式。要写一个基本的服务器,你要实现事件处理器,它处理诸如一个新的客户端连接、新的数据到达和客户端连接中断等情况。在Twisted中,你的事件处理器定义在一个protocol中;你也需要一个factory,当一个新的连接到达时它能够构造这个protocol对象,但是如果你仅仅想创建一个自定义的Protocol类的实例的话,你可以使用来自Twisted的factory,Factory类在模块twisted.internet.protocol中。当你写你的protocol时,使用twisted.internet.protocol模块中的Protocol作为你的父类。当你得到一个连接时,事件处理器connectionMade被调用;当你丢失了一个连接时,connectionLost被调用。从客户端接受数据使用处理器 dataReceived。但是你不能使用事件处理策略向客户端发送数据;要向客户端发送数据,你可以使用self.transport,它有一个 write方法。它也有一个client属性,其中包含了客户端的地址(主机名和端口)。

下面这个例子是一个Twisted版的服务器。其中实例化了Factory并设置了它的protocol属性以便它知道使用哪个protocol与客户端通信(这就是所谓的你的自定义 protocol)。然后你使用factory开始监听指定的端口,factory通过实例化的protocol对象处理连接。监听使用reactor模块中的listenTCP函数。最后,你通过调用reactor模块中的run函数来开始服务器。

# -*- coding:utf-8 -*-
from twisted.internet import protocol, reactor
import datetime

# 定义Protocol类
class TSServProtocol(protocol.Protocol):
    def connectionMade(self):
        clnt = self.clnt = self.transport.getPeer().host
        print '...connected from: ', clnt
    
    def dataReceived(self, data):
        print data
        self.transport.write('[%s] %s' % (datetime.datetime.now(), data))


# 实例化Factory
factory = protocol.Factory()
# 设置factory的protocol属性以便它知道使用哪个protocol与客户端通讯(这就是所谓的自定的protocol)
factory.protocol = TSServProtocol
print 'waiting for connection...'
# 监听指定的端口
reactor.listenTCP(8008, factory)
# 开始运行主程序
reactor.run()</span>
为你的处理目的而写一个自定义的protocol是很容易的。模块twisted.protocols.basic中包含了几个有用的已存在的 protocol,其中的LineReceiver执行dataReceived并在接受到了一个完整的行时调用事件处理器lineReceived。如果当你在接受数据时除了使用lineReceived,还要做些别的,那么你可以使用LineReceiver定义的名为rawDataReceived 事件处理器。下面是一使用LineReceiver的服务器例子:

from twisted.internet import reactor
from twisted.internet.protocol import Factory
from twisted.protocols.basic import LineReceiver

class SimpleLogger(LineReceiver):

    def connectionMade(self):
        print 'Got connection from', self.transport.client
    def connectionLost(self, reason):
        print self.transport.client, 'disconnected'
    def lineReceived(self, line):
        print line

factory = Factory()
factory.protocol = SimpleLogger
reactor.listenTCP(1234, factory)
reactor.run()


第二部分: 一个server实例

# -*- coding: UTF-8 -*-   
# Twisted MMORPG   
from twisted.internet.protocol import Factory   
from twisted.protocols.basic import LineOnlyReceiver   
from twisted.internet import reactor   
import random   
import string   
    
class Game(LineOnlyReceiver):       
   def lineReceived(self, data):     
       self.factory.sendAll("%s" % (data))    
   def getId(self):           
       return str(self.transport.getPeer())   
   def connectionMade(self):           
       print "New User Login:", self.getId()     
       self.transport.write("欢迎来到MMO世界!\n")           
       self.factory.addClient(self)       
   def connectionLost(self, reason):           
       self.factory.delClient(self)
            
class GameFactory(Factory):       
     protocol = Game       
     def __init__(self):           
         self.clients = []   
         self.player = []   
         self.msg=''    
         self.x = range(100,700)   
         self.y = range(100,500)      
     def getPlayerId(self):   
         return len(self.player)   
     def addClient(self, newclient):      
            self.clients.append(newclient)    
     def delClient(self, client):           
         self.clients.remove(client)       
     def sendAll(self, data):   
         #print data   
         if data.find('<policy-file-request/>')!=-1:   
             proto.transport.write('<cross-domain-policy><allow-access-from domain="127.0.0.1" to-ports="*"/></cross-domain-policy>\0')   
         else:   
             arr = data.split(':')   
             prefix = arr[0]   
             content = arr[1]   
             if prefix.find('player')!=-1:   
                  newPlayer = [content,str(random.randrange(200, 600)),str(random.randrange(150,350)),str(random.randrange(1,5))]   
                  self.player.append(newPlayer)   
                  self.msg = ' 玩家 '+content+' 进入游戏!'    
                  #广播所有玩家的位置   
                  temp = []   
                  playerData = ':::'  
                  for pos in self.player:   
                      temp.append(string.join(pos,'---'))   
                  playerData = playerData+string.join(temp,'***')   
                  for proto in self.clients:   
                      proto.transport.write('[系统]: '+self.msg+'\n')   
                      proto.transport.write(playerData)   
             elif prefix.find('pos')!=-1:   
                 playerName,x,y = content.split('---')   
                 i = 0   
                 for p in self.player:   
                     if p[0]==playerName:   
                         p[1]=x   
                         p[2]=y   
                 for proto in self.clients:   
                     proto.transport.write(data)   
             else:   
                 self.msg = data   
                 for proto in self.clients:   
                      proto.transport.write(self.msg+'\n')   
                
reactor.listenTCP(8006, GameFactory())   
reactor.run()


第三部分:Client列子,与第一部分对应

# -*- coding:utf-8 -*-
import datetime
import sys
from twisted.internet import protocol, reactor
from twisted.protocols.basic import LineReceiver


HOST = 'localhost'
PORT = 8008

class TSClntProtocol(protocol.Protocol):
    def sendData(self):
        data = raw_input('> ')
        if data:
            print '...sending %s...' % data
            self.transport.write(data)
        else:
            self.transport.loseConnection()
    
    def connectionMade(self):
        self.sendData()
        
    def dataReceived(self, data):
        print data
        self.sendData()


class TSClntFactory(protocol.ClientFactory):
    protocol = TSClntProtocol
    clientConnectionLost = clientConnectionFailed = lambda self, connector, reason: reactor.stop()
    
    
reactor.connectTCP(HOST, PORT, TSClntFactory())
reactor.run()

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值