最近2018中文字幕在日韩欧美国产成人片_国产日韩精品一区二区在线_在线观看成年美女黄网色视频_国产精品一区三区五区_国产精彩刺激乱对白_看黄色黄大色黄片免费_人人超碰自拍cao_国产高清av在线_亚洲精品电影av_日韩美女尤物视频网站

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
python中怎么利用twisted實(shí)現(xiàn)TCP通訊

這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)碛嘘P(guān)python中怎么利用twisted實(shí)現(xiàn)TCP通訊,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

創(chuàng)新互聯(lián)公司服務(wù)項(xiàng)目包括定海網(wǎng)站建設(shè)、定海網(wǎng)站制作、定海網(wǎng)頁制作以及定海網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢(shì)、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,定海網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到定海省份的部分城市,未來相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!

0.寫在前面

不管是服務(wù)器端還是客戶端,都是通過twistedreactor來啟動(dòng)的,所以首先就需要導(dǎo)入twisted.internet包下的reactor模塊

reactor模塊的源碼中可以看出reactor模塊其實(shí)是由多個(gè)接口組成的,并且提示了具體內(nèi)容需要查看twisted.internet包下的interfaces模塊中每個(gè)接口的具體注釋說明

當(dāng)然從reactor模塊的注釋中也說明了twisted不止可以用于TCP服務(wù),而是提供了網(wǎng)絡(luò)方面的API、線程、調(diào)度等功能, 但是本次的實(shí)驗(yàn)僅僅測(cè)試一下TCP的服務(wù)器端和客戶端

reactor注釋中提到的支持的接口:
@see: L{IReactorCore}
@see: L{IReactorTime}
@see: L{IReactorProcess}
@see: L{IReactorTCP}
@see: L{IReactorSSL}
@see: L{IReactorUDP}
@see: L{IReactorMulticast}
@see: L{IReactorUNIX}
@see: L{IReactorUNIXDatagram}
@see: L{IReactorFDSet}
@see: L{IReactorThreads}
@see: L{IReactorPluggableResolver}

1.TCP服務(wù)器端

·reactor反應(yīng)器

根據(jù)上面reactor模塊的注釋,發(fā)現(xiàn)和TCP相關(guān)的需要查看interfaces模塊下的IReactorTCP接口,所以接下來我們移步至IReactorTCP接口

IReactorTCP接口中有兩個(gè)方法listenTCPconnectTCP,不管從方法名還是其說明都可以看出,前者是監(jiān)聽一個(gè)端口提供TCP服務(wù),后者是連接到服務(wù)端的TCP客戶端

def listenTCP(port, factory, backlog=50, interface=''):
def connectTCP(host, port, factory, timeout=30, bindAddress=None):

所以要開啟一個(gè)TCP服務(wù)端,我們需要用到的是listenTCP方法,這個(gè)方法有4個(gè)參數(shù)

參數(shù)名意義默認(rèn)值
port監(jiān)聽的端口,也就是TCP服務(wù)啟動(dòng)的端口-
factory服務(wù)端的工廠類(根據(jù)注釋中的提示:詳情見twisted.internet包下的protocol模塊中的ServerFactory類)-
backlog監(jiān)聽隊(duì)列,響應(yīng)線程數(shù)50
interface要綁定到的本地IPv4或IPv6地址,默認(rèn)為空標(biāo)示所有IPv4的地址‘’

·Factory工廠類

在設(shè)置了前兩個(gè)參數(shù)以后,然后通過下面兩行代碼就可以啟動(dòng)TCP服務(wù)了

reactor.listenTCP(port, ServerFactory())
reactor.run()

但是,此時(shí)啟動(dòng)的服務(wù)是有問題的,當(dāng)有客戶端連接到該服務(wù)的時(shí)候就會(huì)報(bào)錯(cuò)

---  ---
  File "D:\MyWorkSpaces\tools\Anaconda3\envs\tf2\lib\site-packages\twisted\internet\tcp.py", line 1427, in doRead
    self._buildAddr(addr))
  File "D:\MyWorkSpaces\tools\Anaconda3\envs\tf2\lib\site-packages\twisted\internet\protocol.py", line 140, in buildProtocol
    p = self.protocol()
builtins.TypeError: 'NoneType' object is not callable

根據(jù)錯(cuò)誤提示,我們找到了問題的原因:

在客戶端連接到服務(wù)器端的時(shí)候,會(huì)調(diào)用Factory類(ServerFactory的父類)中的buildProtocol方法來建立通訊協(xié)議(這里可以理解為客戶端和服務(wù)器端之間讀寫的實(shí)現(xiàn)方法),其中需要調(diào)用self.protocol所指向的方法來初始化這個(gè)協(xié)議

然而此時(shí)的protocol卻是None,所以在協(xié)議的初始化階段出錯(cuò)了

·Protocol協(xié)議類

再次研究一下protocol模塊中的Factory類,發(fā)現(xiàn)類方法forProtocol是用于創(chuàng)建factory實(shí)例的,但是需要給定一個(gè)protocol實(shí)例

很好,我們的目標(biāo)又近了一步,下面繼續(xù)研究Protocol

同樣在protocol模塊中,我們找到了Protocol類,他繼承自BaseProtocol類,總共有下面幾個(gè)方法

  • BaseProtocol.makeConnection:用于開啟連接,當(dāng)連接開啟后會(huì)回調(diào)connectionMade方法

  • BaseProtocol.connectionMade:未實(shí)現(xiàn)。當(dāng)連接成功以后回調(diào)該方法

  • Protocol.logPrefix:返回當(dāng)前類的類名,用于日志log

  • Protocol.dataReceived:未實(shí)現(xiàn)。當(dāng)收到請(qǐng)求時(shí)被調(diào)用的方法

  • Protocol.connectionLost:未實(shí)現(xiàn)。當(dāng)連接斷開時(shí)調(diào)用的方法

所以現(xiàn)在我們只要繼承Protocol類,寫一個(gè)自己的實(shí)現(xiàn)協(xié)議就可以了,并且只需要實(shí)現(xiàn)父類中未實(shí)現(xiàn)的3個(gè)方法

為了簡(jiǎn)單一些,在connectionMadeconnectionLost方法中我們只記錄一下客戶端的連接信息并輸出一下log,而在dataReceived方法中我們將收到的信息打印出來,并在5s過后返回客戶端一條消息

class TcpServer(Protocol)::
    CLIENT_MAP = {}  # 用于保存客戶端的連接信息

    def connectionMade(self):
        addr = self.transport.client  # 獲取客戶端的連接信息
        print("connected", self.transport.socket)
        TcpServer.CLIENT_MAP[addr] = self

    def connectionLost(self, reason):
        addr = self.transport.client  # 獲取客戶端的連接信息
        if addr in TcpServer.CLIENT_MAP:
            print(addr, "Lost Connection from Tcp Server", 'Reason:', reason)
            del TcpServer.CLIENT_MAP[addr]

    def dataReceived(self, tcp_data):
        addr = self.transport.client  # 獲取客戶端的連接信息
        nowTime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        try:
            msg = tcp_data.decode("utf-8")
            print("Received msg", msg, "from Tcp Client", addr)

            time.sleep(5)
            str = "來自服務(wù)器的響應(yīng) " + nowTime
            self.transport.write(str.encode("utf-8"))

        except BaseException as e:
            print("Comd Execute Error from", addr, "data:", tcp_data)
            str = "服務(wù)器發(fā)生異常 " + nowTime
            self.transport.write(str.encode("utf-8"))

·啟動(dòng)TCP服務(wù)

好,Protocol類已經(jīng)實(shí)現(xiàn)了,我們用他來創(chuàng)建工廠實(shí)例并啟動(dòng)TCP服務(wù)

    port = 9527
    serverFactory = Factory.forProtocol(TcpServer)
    reactor.listenTCP(port, serverFactory)
    print("#####", "Starting TCP Server on", port, "#####")
    reactor.run()

TCP服務(wù)成功啟動(dòng),并且客戶端連接上來以后也沒有報(bào)錯(cuò)

D:\MyWorkSpaces\tools\Anaconda3\envs\tf2\python.exe D:/MyWorkSpaces/projects/all/sample/python/twisted/server.py
##### Starting TCP Server on 9527 #####
connected 
Received msg 你好服務(wù)器,我是客戶端 2019-08-10 11:13:09 from Tcp Client ('127.0.0.1', 3440)

2.TCP客戶端

·reactor反應(yīng)器

有了服務(wù)器的經(jīng)驗(yàn),我們回來看reactor模塊中IReactorTCP接口里的connectTCP方法,這個(gè)方法一共有5個(gè)參數(shù)

參數(shù)名意義默認(rèn)值
host服務(wù)器地址,IPv4或IPv6-
prot服務(wù)器端口-
factory客戶端的工廠類,(根據(jù)注釋中的提示:詳情見twisted.internet包下的protocol模塊中的ClientFactory類)-
timeout連接超時(shí)時(shí)間,單位s30
bindAddress本地的地址,格式為(host,port)的元祖None

同樣也很簡(jiǎn)單,我們只要以下兩行代碼就可以啟動(dòng)客戶端了,但是和服務(wù)端類似,在這之前我們也需要實(shí)現(xiàn)一個(gè)Factory工廠類和Protocol協(xié)議類的實(shí)例

reactor.connectTCP(host, port, factory)
reactor.run()

·Factory工廠類

根據(jù)connectTCP方法的注釋說明,我們直接可以找到ClientFactory類,類中有3個(gè)方法需要實(shí)現(xiàn)

  • ClientFactory.startedConnecting:未實(shí)現(xiàn)。開啟連接時(shí)會(huì)調(diào)用該方法

  • ClientFactory.clientConnectionFailed:未實(shí)現(xiàn)。連接失敗時(shí)會(huì)調(diào)用該方法

  • ClientFactory.clientConnectionLost:未實(shí)現(xiàn)。連接斷開時(shí)會(huì)調(diào)用該方法

同樣,為了簡(jiǎn)單,我們?cè)?code>startedConnecting方法中只做一下日志log的記錄,在clientConnectionFailedclientConnectionLost方法中記錄入職log以后隔30s以后重試連接

class TcpClientFactory(ClientFactory):

    def startedConnecting(self, connector):
        print("Starting Connecting To Tcp Server", (connector.host, connector.port))

    def clientConnectionLost(self, connector, reason):
        print("Lost Connection from Tcp Server", (connector.host, connector.port), 'Reason:', reason)
        time.sleep(30)
        connector.connect()

    def clientConnectionFailed(self, connector, reason):
        print("Failed To Connect To Tcp Server", (connector.host, connector.port), 'Reason:', reason)
        time.sleep(30)
        connector.connect()

啟動(dòng)TCP客戶端,我們發(fā)現(xiàn)了和第一次啟動(dòng)服務(wù)端時(shí)一樣的錯(cuò)誤,這次我們有經(jīng)驗(yàn)了,因?yàn)樯倭?code>Protocol類的實(shí)現(xiàn)

---  ---
  File "D:\MyWorkSpaces\tools\Anaconda3\envs\tf2\lib\site-packages\twisted\internet\selectreactor.py", line 149, in _doReadOrWrite
    why = getattr(selectable, method)()
  File "D:\MyWorkSpaces\tools\Anaconda3\envs\tf2\lib\site-packages\twisted\internet\tcp.py", line 627, in doConnect
    self._connectDone()
  File "D:\MyWorkSpaces\tools\Anaconda3\envs\tf2\lib\site-packages\twisted\internet\tcp.py", line 641, in _connectDone
    self.protocol = self.connector.buildProtocol(self.getPeer())
  File "D:\MyWorkSpaces\tools\Anaconda3\envs\tf2\lib\site-packages\twisted\internet\base.py", line 1157, in buildProtocol
    return self.factory.buildProtocol(addr)
  File "D:\MyWorkSpaces\tools\Anaconda3\envs\tf2\lib\site-packages\twisted\internet\protocol.py", line 140, in buildProtocol
    p = self.protocol()
builtins.TypeError: 'NoneType' object is not callable

·Protocol協(xié)議類

和服務(wù)器端使用的是同一個(gè)Protocol父類,這里稍微做點(diǎn)和服務(wù)器端不同的事,實(shí)現(xiàn)connectionMade方法時(shí)我們往服務(wù)器端發(fā)送一條消息

class TcpClient(Protocol):
    SERVER_MAP = {}

    def connectionMade(self):
        addr = self.transport.addr  # 獲取服務(wù)器端的連接信息
        print("connected", self.transport.socket)
        client_ip = addr[0]
        TcpClient.SERVER_MAP[client_ip] = self
        nowTime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        str = "你好服務(wù)器,我是客戶端 " + nowTime
        self.transport.write(str.encode("utf-8"))  # 向服務(wù)器發(fā)送信息

    def connectionLost(self, reason):
        addr = self.transport.addr  # 獲取服務(wù)器端的連接信息
        client_ip = addr[0]
        if client_ip in TcpClient.SERVER_MAP:
            del TcpClient.SERVER_MAP[client_ip]

    def dataReceived(self, tcp_data):
        addr = self.transport.addr  # 獲取服務(wù)器端的連接信息
        nowTime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        try:
            msg = tcp_data.decode("utf-8")
            print("Received msg", msg, "from Tcp Server", addr)

            time.sleep(5)
            str = "來自客戶端的響應(yīng) " + nowTime
            self.transport.write(str.encode("utf-8"))

        except BaseException as e:
            print("Comd Execute Error from", addr, "data:", tcp_data)
            str = "客戶端發(fā)生異常 " + nowTime
            self.transport.write(str.encode("utf-8"))

·啟動(dòng)TCP客戶端

因?yàn)樵趧?chuàng)建Factory類的時(shí)候和服務(wù)器端有些不一樣,之前服務(wù)器端我們是通過Factory.forProtocol方法來實(shí)例化工廠對(duì)象的,而在客戶端的時(shí)候我們是繼承了Factory類的子類ClientFactory來實(shí)現(xiàn)的,所以我們需要重寫buildProtocol方法來設(shè)置protocol實(shí)例

TcpClientFactory類中重寫buildProtocol方法:

class TcpClientFactory(ClientFactory):
    def buildProtocol(self, addr):
        print("Connected To Tcp Server", addr)
        self.protocol = TcpClient()
        return self.protocol

然后用以下代碼來啟動(dòng)TCP客戶端:

    host = "127.0.0.1"
    port = 9527
    reactor.connectTCP(host, port, TcpClientFactory())
    reactor.run()

TCP客戶端成功啟動(dòng),并且連接上服務(wù)器端以后也沒有報(bào)錯(cuò)

D:\MyWorkSpaces\tools\Anaconda3\envs\tf2\python.exe D:/MyWorkSpaces/projects/all/sample/python/twisted/client.py
Starting Connecting To Tcp Server ('127.0.0.1', 9527)
Connected To Tcp Server IPv4Address(type='TCP', host='127.0.0.1', port=9527)
connected 
Received msg 來自服務(wù)器的響應(yīng) 2019-08-10 11:57:42 from Tcp Server ('127.0.0.1', 9527)

上述就是小編為大家分享的python中怎么利用twisted實(shí)現(xiàn)TCP通訊了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。


網(wǎng)頁名稱:python中怎么利用twisted實(shí)現(xiàn)TCP通訊
文章來源:http://fisionsoft.com.cn/article/gicgid.html