zoukankan      html  css  js  c++  java
  • Python Twisted 框架中 socket通信

    转载:http://blog.csdn.net/jackyyen/archive/2009/04/13/4069887.aspx

    // 部分一

    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函数来开始服务器。

    代码
    from twisted.internet import reactor
    from twisted.internet.protocol import Protocol, Factory

    # 定义你Protocol类
    class SimpleLogger(Protocol):

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


    # 实例化Factory

    factory
    = Factory()

    # 设置factory的protocol属性以便它知道使用哪个protocol与客户端通信(这就是所谓的你的自定义
    #
    protocol)

    factory.protocol
    = SimpleLogger

    # 监听指定的端口

    reactor.listenTCP(
    1234, factory)

    # 开始运行主程序
    reactor.run()

    为你的处理目的而写一个自定义的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例子,与前文不相关

    代码
    from twisted.internet.protocol import ClientCreator, Protocol
    from twisted.protocols.basic import LineReceiver
    from twisted.internet import reactor
    import sys

    class Sender(Protocol):
    def sendCommand(self, command):
    print "invio", command
    self.transport.write(command)

    def dataReceived(self, data):
    print "DATA", data

    PORT
    = 5005
    HOST
    = 'localhost'

    def sendCommand(command):
    def test(d):
    print "Invio ->", command
    d.sendCommand(command)
    c
    = ClientCreator(reactor, Sender)
    c.connectTCP(HOST, PORT).addCallback(test)

    if __name__ == '__main__':
    if len(sys.argv) != 2 or sys.argv[1] not in ['stop', 'next_call', 'force']:
    sys.stderr.write(
    'Usage: %s: {stop|next_call|force}\n' % sys.argv[0])
    sys.exit(
    1)
    sendCommand(sys.argv[
    1]+'\n')
    reactor.run()
  • 相关阅读:
    MVC概念性的内容
    类 class
    php获取真实IP地址
    面向对象static静态的属性和方法的调用
    smarty 入门2(个人总结)
    smarty入门
    读取文件内容fopen,fgets,fclose
    mysql常用命令
    mybatis查询的三种方式
    MyBatis 映射文件
  • 原文地址:https://www.cnblogs.com/sevenyuan/p/1880681.html
Copyright © 2011-2022 走看看