Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5119899
  • 博文数量: 921
  • 博客积分: 16037
  • 博客等级: 上将
  • 技术积分: 8469
  • 用 户 组: 普通用户
  • 注册时间: 2006-04-05 02:08
文章分类

全部博文(921)

文章存档

2020年(1)

2019年(3)

2018年(3)

2017年(6)

2016年(47)

2015年(72)

2014年(25)

2013年(72)

2012年(125)

2011年(182)

2010年(42)

2009年(14)

2008年(85)

2007年(89)

2006年(155)

分类: Python/Ruby

2011-11-21 14:40:35

#Author:pako

 

#Email/gtalk:zealzpc@gmail.com

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

 

 

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

 

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

 

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

  3. """
  4. Example socket server using Twisted.

  5. @see: U{Documentation for this example<}

  6. @since: 0.1
  7. """


  8. try:
  9.     import twisted
  10. except ImportError:
  11.     print "This examples requires the Twisted framework. Download it from "
  12.     raise SystemExit

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

  15. from datetime import datetime
  16. import pyamf


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

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

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

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

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

  56.     def start(self):
  57.         self.started = True
  58.         self.sendTime()

  59.     def stop(self):
  60.         self.started = False

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


  71. class TimerFactory(Factory):
  72.     protocol = TimerProtocol
  73.     #最大链接数
  74.     max_connections = 1000

  75.     def __init__(self):
  76.         self.number_of_connections = 0


  77. class SocketPolicyProtocol(Protocol):
  78.     """
  79.     Serves strict policy file for Flash Player >= 9,0,124.
  80.     
  81.     @see: U{}
  82.     """
  83.     def connectionMade(self):
  84.         self.buffer = ''

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

  87.         if self.buffer.startswith(''):
  88.             self.transport.write(self.factory.getPolicyFile(self))
  89.             self.transport.loseConnection()


  90. class SocketPolicyFactory(Factory):
  91.     protocol = SocketPolicyProtocol

  92.     def __init__(self, policy_file):
  93.         """
  94.         @param policy_file: Path to the policy file definition
  95.         """
  96.         self.policy_file = policy_file

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

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


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

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

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

 

在例子中还提供了另外一个文件:time.tac。懂twisted的人应该就知道了,这是一份twistd脚本,可以直接通过twisted自带的twistd来执行。里面import了  server.py中已经写好的TimerFactory,然后定义了一个application类,这样就可以通过twistd命令来执行了,twistd是什么可以参考官方文档/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上不行。

 

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

  3. import sys, os

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

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


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

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

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

  14. timerService.setServiceParent(application)
  15. socketPolicyService.setServiceParent(application)

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

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

 

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

  3. """
  4. Python client for socket example.

  5. @since: 0.5
  6. """


  7. import socket
  8. import pyamf

  9. from server import appPort, host


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

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

  20.     def start(self):
  21.         msg = ''

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

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

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

  33.             msg = msg + amf

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

  36.         return msg

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


  40. if __name__ == '__main__':
  41.     from optparse import OptionParser

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

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

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

  52.     try:
  53.         client.start()
  54.     except KeyboardInterrupt:
  55.         client.stop()

 原文地址:

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

阅读(2255) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~