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')
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传送多数据的时候,接受到是一起接受呢的主要内容,如果未能解决你的问题,请参考以下文章

Twisted 简介

python网络框架Twisted

Python 将 http post body 扭曲转发到 tcp 端口

Twisted 综述

如何通过python twisted HTTPClient生成POST和GET请求?

Twisted 中的多重响应