`

用twisted创建tcp socket长链接amf server服务

阅读更多

#Author:pako

 

#Email/gtalk:zealzpc@gmail.com

这是pyamf安装包里的例子,总的来说用pyamf来写server的各种例子还是很全的,包括django,gae,twisted,web2py等等,基本python常用的网络框架都有。现在很多网页游戏都是前端flash,那么和server端通信基本就用 amf了,如果server端的功能只是存储一些统计,或者对数据库的增删改查,那么一般的http短连接服务就能搞定了,以上提到的这些框架也都写起来比较简单,比如可以看django的例子http://www.pyamf.org/tutorials/gateways/django.html,寥寥数行就搞定了,python嘛。

 

 

  但有时候需求不是这样的需要flash和server保持一个长连接来不断的进行通信改怎么搞呢?此时在pyamf的网站上看到了sockey这一段,正是我们想要的。

 

  先看下server端的代码:server.py

 

 

# Copyright (c) The PyAMF Project.
# See LICENSE.txt for details.

"""
Example socket server using Twisted.

@see: U{Documentation for this example<http://pyamf.org/tutorials/actionscript/socket.html>}

@since: 0.1
"""


try:
    import twisted
except ImportError:
    print "This examples requires the Twisted framework. Download it from http://twistedmatrix.com"
    raise SystemExit

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

from datetime import datetime
import pyamf


class TimerProtocol(Protocol):
    interval = 1.0 # 客户端链接到server后,server往客户端发送时间的间隔
    encoding = pyamf.AMF3
    timeout = 20 #客户端链接到server后多少时间不操作就断开链接的timeout

    def __init__(self):
        self.started = False
        #设置编码器
        self.encoder = pyamf.get_encoder(self.encoding)、
        #设置server端将数据编码成amf后存放的缓存地址
        self.stream = self.encoder.stream

    def connectionLost(self, reason):
        Protocol.connectionLost(self, reason)
        print "locst connection:",reason
        #客户端没断开一个链接,总连接数-1
        self.factory.number_of_connections -= 1
        print "number_of_connections:",self.factory.number_of_connections
    def connectionMade(self):
        #如果服务器连接数超过最大连接数,拒绝新链接建立
        if self.factory.number_of_connections >= self.factory.max_connections:
            self.transport.write('Too many connections, try again later')
            self.transport.loseConnection()

            return
        #总连接数+1
        self.factory.number_of_connections += 1
        self.timeout_deferred = reactor.callLater(TimerProtocol.timeout, self.transport.loseConnection)

    def dataReceived(self, data):
        #去除server收到client数据两端的空格
        data = data.strip()
        #如果收到的是'start'命令
        if data == 'start':
            # start sending a date object that contains the current time
            if not self.started:
                self.start()
        elif data == 'stop':
            self.stop()
        #每次执行完客户端请求后重置timeout,重新开始计算无操作时间。
        if self.timeout_deferred:
            self.timeout_deferred.cancel()
            self.timeout_deferred = reactor.callLater(TimerProtocol.timeout, self.transport.loseConnection)

    def start(self):
        self.started = True
        self.sendTime()

    def stop(self):
        self.started = False

    def sendTime(self):
        if self.started:
            #往缓存流里写入信息,用编码器进行amf编码
            self.encoder.writeElement(datetime.now())
            #返回给客户端编码后的信息
            self.transport.write(self.stream.getvalue())
            #重置缓存流
            self.stream.truncate()
            #每隔self.interval的时间再发送一次amf信息
            reactor.callLater(self.interval, self.sendTime)


class TimerFactory(Factory):
    protocol = TimerProtocol
    #最大链接数
    max_connections = 1000

    def __init__(self):
        self.number_of_connections = 0


class SocketPolicyProtocol(Protocol):
    """
    Serves strict policy file for Flash Player >= 9,0,124.
    
    @see: U{http://adobe.com/go/strict_policy_files}
    """
    def connectionMade(self):
        self.buffer = ''

    def dataReceived(self, data):
        self.buffer += data

        if self.buffer.startswith('<policy-file-request/>'):
            self.transport.write(self.factory.getPolicyFile(self))
            self.transport.loseConnection()


class SocketPolicyFactory(Factory):
    protocol = SocketPolicyProtocol

    def __init__(self, policy_file):
        """
        @param policy_file: Path to the policy file definition
        """
        self.policy_file = policy_file

    def getPolicyFile(self, protocol):
        return open(self.policy_file, 'rt').read()

#设置域名,端口。
host = 'localhost'
appPort = 8000
policyPort = 843
policyFile = 'socket-policy.xml'


if __name__ == '__main__':
    from optparse import OptionParser
    #设置server启动选项
    parser = OptionParser()
    parser.add_option("--host", default=host,
        dest="host", help="host address [default: %default]")
    parser.add_option("-a", "--app-port", default=appPort,
        dest="app_port", help="Application port number [default: %default]")
    parser.add_option("-p", "--policy-port", default=policyPort,
        dest="policy_port", help="Socket policy port number [default: %default]")
    parser.add_option("-f", "--policy-file", default=policyFile,
        dest="policy_file", help="Location of socket policy file [default: %default]")
    (opt, args) = parser.parse_args()

    print "Running Socket AMF gateway on %s:%s" % (opt.host, opt.app_port)
    print "Running Policy file server on %s:%s" % (opt.host, opt.policy_port)
     
    reactor.listenTCP(int(opt.app_port), TimerFactory(), interface=opt.host)
    reactor.listenTCP(int(opt.policy_port), SocketPolicyFactory(opt.policy_file),
                      interface=opt.host)
    reactor.run()

 

 

 

里面最主要干活的就是TimerProtocol这个类。

 

在例子中还提供了另外一个文件:time.tac。懂twisted的人应该就知道了,这是一份twistd脚本,可以直接通过twisted自带的twistd来执行。里面import了  server.py中已经写好的TimerFactory,然后定义了一个application类,这样就可以通过twistd命令来执行了,twistd是什么可以参考官方文档http://twistedmatrix.com/documents/current/core/howto/application.html 本文就不细说了。

 

debug模式启动server:twistd -noy timer.tac

 

daemo模式启动server:twistd -oy timer.tac

 

你也可以直接启动server.py文件:python server.py、

 

区别就是第二种直接后台运行了在linux,你看不到报错和调试信息,当然windows上不行。

 

 

 

# Copyright (c) The PyAMF Project.
# See LICENSE for details.

import sys, os

sys.path.append(os.getcwd())

from twisted.application import internet, service
from server import TimerFactory, SocketPolicyFactory
from server import appPort, policyPort


timer = TimerFactory()
policy = SocketPolicyFactory('socket-policy.xml')

# this is the important bit
application = service.Application('pyamf-socket-example')

timerService = internet.TCPServer(appPort, timer)
socketPolicyService = internet.TCPServer(policyPort, policy)

timerService.setServiceParent(application)
socketPolicyService.setServiceParent(application)
 

 

最后就是找个客户端来连接测测,例子里也提供了一个写好的flash,你打开通一个目录下的index.html就可以看看效果了。

 

 

 

  例子里也给你准备了python的客户端。

 

# Copyright (c) The PyAMF Project.
# See LICENSE for details.

"""
Python client for socket example.

@since: 0.5
"""


import socket
import pyamf

from server import appPort, host


class AmfSocketClient(object):
    def __init__(self):
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    def connect(self, host, port):
        print "Connecting to socket server on %s:%d" % (host, port)
        try:
            self.sock.connect((host, port))
            print "Connected to server.\n"
        except socket.error, e:
            raise Exception("Can't connect: %s" % e[1])

    def start(self):
        msg = ''

        # tell server we started listening
        print "send request: start"
        try:
            self.sock.send('start')
        except socket.error, e:
            raise Exception("Can't connect: %s" % e[1])

        while len(msg) < 1024:
            # read from server
            amf = self.sock.recv(1024)

            if amf == '':
                print "Connection closed."

            msg = msg + amf

            for obj in pyamf.decode(amf):
                print obj

        return msg

    def stop(self):
        print "send request: stop"
        self.sock.send('stop')


if __name__ == '__main__':
    from optparse import OptionParser

    parser = OptionParser()
    parser.add_option("-p", "--port", default=appPort,
        dest="port", help="port number [default: %default]")
    parser.add_option("--host", default=host,
        dest="host", help="host address [default: %default]")
    (options, args) = parser.parse_args()

    host = options.host
    port = int(options.port)

    client = AmfSocketClient()
    client.connect(host, port)

    try:
        client.start()
    except KeyboardInterrupt:
        client.stop()   

 原文地址:http://www.pyamf.org/tutorials/actionscript/socket.html

代码就在pyamf安装包的pyamf / doc / tutorials / examples / actionscript / socket这个目录里。

 

 

欢迎讨论。

分享到:
评论
1 楼 simomo 2011-07-01  
我用的是amfast,这个支持长轮训和streamingchannel
不过,貌似pyamf现在也是用C写编码器

相关推荐

    twisted编写TCP服务器

    Twisted被设计为一个非常灵活的框架,可以使用它编写强大的服务器.这种灵活性的代价是当你编写服务器的时候需要分好几层. 本文档描述协议层,在这里定义协议的解析和处理.如果你正在编写一个应用的话这应该是你读的第...

    python如何通过twisted搭建socket服务

    主要介绍了python如何通过twisted搭建socket服务,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    python twisted server端例子

    python twisted框架 服务器端 示例

    python基础教程:python如何通过twisted搭建socket服务

    这篇文章主要介绍了python如何通过twisted搭建socket服务,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 服务端 # -*- coding: utf-8 -*- # @Time : 2018/9/19...

    python twisted 简单服务器

    python twisted 简单服务器,服务器接收客户端发送的相应的信息,根据信息进行相应的返回数据

    Twisted系列教程.pdf

    第一部分:Twisted理论基础 第二部分:异步编程初探与reactor模式 第三部分:初步认识Twisted 第四部分:由Twisted支持的诗歌客户端 第一个twisted支持的诗歌服务器 第一滴心血 第五部分:由Twisted支持的诗歌...

    twisted实现的游戏服务器

    使用twisted开发的游戏服务器端,客户端为unity3d,请结合使用

    Twisted Network Programming Essentials 2nd Edition

    Start by building basic TCP clients and servers, and then focus on deploying production-grade applications with the Twisted Application infrastructure. Along the way, you can play with and extend ...

    Twisted Network Programming Essentials, 2nd Edition

    Twisted comes with client and server implementations for all of its protocols, as well as utilities that make it easy to configure and deploy production-grade Twisted applications from the command ...

    Twisted Network Programming Essentials

    Start by building basic TCP clients and servers, and then focus on deploying production-grade applications with the Twisted Application infrastructure. Along the way, you can play with and extend ...

    autobahn-python, 在 python 中为 Twisted 和 asyncio,web socket和,.zip

    autobahn-python, 在 python 中为 Twisted 和 asyncio,web socket和, Autobahn|Pythonweb socket & WAMP用于 Twisted 和asyncio上的python 。 快速链接: 源代码 - 文档- web socket示例- web WebSocke

    Twisted-19.10.0-cp38-cp38.rar

    Twisted是用于Internet应用程序的基于事件的框架,支持Python 2.7和Python 3.5+...twisted.names:DNS客户端和用于创建自己的DNS服务器的工具 twisted.trial:一种单元测试框架,可以与基于Twisted的代码很好地集成。

    Python twisted教程

    我学习和使用twisted已经好几年了,通过这几年的学习和工作我得出的结论就是:学习twisted困难的地方就是对异步编程的理解而不是怎样去用twisted 的函数去写代码. twisted 的代码写的都很简洁和清晰,而且有很好的注释...

    Twisted-17.1.0-cp36-cp36m-win_amd64.whl

    Twisted是用Python实现的基于事件驱动的网络引擎框架。Twisted诞生于2000年初,在当时的网络游戏开发者看来,无论他们使用哪种语言,手中都鲜有可兼顾扩展性及跨平台的网络库。Twisted的作者试图在当时现有的环境下...

    Python Twisted-22.10.0-py3-none-any

    Twisted是用Python实现的基于事件驱动的网络引擎框架。Twisted诞生于2000年初,在当时的网络游戏开发者看来,无论他们使用哪种语言,手中都鲜有可兼顾扩展性及跨平台的网络库。Twisted的作者试图在当时现有的环境下...

    twisted入门教程源码

    Twisted Info Twisted入门教程源码

    twisted资料twisted资料

    twisted资料twisted资料twisted资料

    Twisted与异步编程入门

    Twisted与异步编程入门,最好的入门资源。

Global site tag (gtag.js) - Google Analytics