python twisted 写tcp 客户端 服务器 为啥self.transport.write传送多数据的时候,接受到是一起接受呢
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python twisted 写tcp 客户端 服务器 为啥self.transport.write传送多数据的时候,接受到是一起接受呢相关的知识,希望对你有一定的参考价值。
因为tcp socket只是传送一个段连续的数据流,如果你write:
self.transport.write('Z')
self.transport.write('Z')
因为三个write是连续的,所以对socket来说,它要传的就是用hex表示的'5a 5a 5a'这样一段数据,你分开写或者一次写对socket来说没有什么区别。
tcp socket的另一端需要接受多次的,要么是你要传送的数据太大,一个packet装不下,要么就是两次传送之间的时间有间隔,会形成两个packet。
一般的处理是你需要另外的一个Application Layer的protocol,比如最简单的你用\\r\\n来分隔每一个write,然后在接收到的时候可以在数据里找到\\r\\n,然后就可以分别处理每一个write了。
参考技术A twisted似乎是异常通讯。也支持同步通讯。你找一找,这两个方法的应该都有例子。很早以前用过它开发,当时想开发出高性能的服务器。后来失败了。 不过现在有了gevent, epoll,pypy等等。也许它现在是可行的。
python网络框架Twisted
什么是Twisted
Twisted是一个用python语言写的事件驱动网络框架,它支持很多种协议,包括UDP,TCP,TLS和其他应用层协议,比如HTTP,SMTP,NNTM,IRC,XMPP/Jabber。
一个Twisted程序由reactor发起的主循环和一些回调函数组成。当事件发生了,比如一个client连接到了server,这时候服务器端的事件会被触发执行。
官方的简单例子启动Twisted:
from twisted.internet import reactor def hello(): print(‘Hello from the reactor loop!‘) print(‘Lately I feel like I\‘m stuck in a rut.‘) # 将函数hello传入reactor reactor.callWhenRunning(hello) print(‘Starting the reactor.‘) # 启动reactor后调用hello函数 reactor.run()
退出Twisted:
from twisted.internet import reactor class Countdown(object): counter=5 def count(self): if self.counter==0: # 停止reactor的循环监听 reactor.stop() else: print(self.counter,"...") self.counter-=1 # 注册一个回调函数第一个参数是几秒回调,第二个参数是回调函数 reactor.callLater(1,self.count) reactor.callWhenRunning(Countdown().count) print("start") reactor.run() print("stop!") #执行结果 start 5 ... 4 ... 3 ... 2 ... 1 ... stop!
twisted中出现异常,程序并不会崩溃:
from twisted.internet import reactor # 异常函数 def falldown(): raise Exception(‘I fall down.‘) # 重启函数 def upagain(): print(‘But I get up again.‘) # 注销stop,程序会继续执行,并不会崩溃,说明twisted的健壮性 reactor.stop() reactor.callWhenRunning(falldown) reactor.callWhenRunning(upagain) print(‘Starting the reactor.‘) reactor.run()
用Twisted写一个简单的TCP服务器
下面的代码是一个TCPServer,这个server记录客户端发来的数据信息。
import sys from twisted.internet.protocol import ServerFactory from twisted.protocols.basic import LineReceiver from twisted.python import log from twisted.internet import reactor class CmdProtocol(LineReceiver): # 分隔符 delimiter = "\n" # 连接成功事件,可重载 def connectionMade(self): # 获取客户端的ip # getPeer获取客户端信息 # getHost获取服务端信息 self.client_ip=self.transport.getPeer().host# 日志记录来访客户端的ip log.msg("Client connection from %s" % self.client_ip) # 如果连接的客服端数量大于最大连接数,那么就关闭连接 if len(self.factory.clients)>=self.factory.clients_max: log.msg("Too many connections. bye !") self.client_ip=None # 关闭连接 self.transport.loseConnection() else: self.factory.clients.append(self.client_ip) # 连接断开事件,可重载,依靠reason区分断开类型 def connectonLost(self,reason): log.msg(‘Lost client connection. Reason: %s‘ % reason) if self.client_ip: self.factory.clients.remove(self.client_ip) # 继承父类的方法,用于分发事件,不要重载 def lineReceived(self, line): log.msg(‘Cmd received from %s : %s‘ % (self.client_ip, line)) class MyFactory(ServerFactory): # 指向一个协议类,我们自定义的 protocol = CmdProtocol def __init__(self,clients_max=10): self.clients_max=clients_max self.clients=[] # 配置将日志输出到stdout log.startLogging(sys.stdout) reactor.listenTCP(9999,MyFactory(2)) reactor.run()
#在cmd中输入:
Telnet 127.0.0.1 9999 测试
以上是关于python twisted 写tcp 客户端 服务器 为啥self.transport.write传送多数据的时候,接受到是一起接受呢的主要内容,如果未能解决你的问题,请参考以下文章
Python 将 http post body 扭曲转发到 tcp 端口