2014-01-07 281 views
-2

當服務器和客戶端都處於不同的終端窗口時,我無法獲得服務器和客戶端之間的通信。我可以讓他們都連接雖然不是它們的輸出實際發送到每個人窗戶向 客戶:客戶端 - 服務器聊天Twisted,Python

from twisted.internet import reactor, stdio, protocol 

from twisted.protocols import basic 


class Echo(basic.LineReceiver): 

    def connectionMade(self): 

     print "Welcome to the Chat, you have now connected" 


    def lineReceived(self, line): 

     self.sendLine(line) 

     if line=="exit": 

      connectionLost() 



    def connectionLost(self): 

     self.transport.loseConnection() 


class EchoClientFactory(protocol.ClientFactory): 

    protocol = Echo 


factory = EchoClientFactory() 

reactor.connectTCP("localhost", ...., factory) 

reactor.run() 

服務器:

from twisted.internet import reactor, protocol, stdio 

from twisted.protocols import basic 


class Echo(basic.LineReceiver): 

    print "Welcome to Chat" 

    def connectionMade(self): 

      print "A new client has connected" 

    def lineReceived(self, line): 

      self.sendLine(line) 

      if line=="exit": 

      connectionLost() 


    def connectionLost(self): 

     self.transport.loseConnection() 



class EchoServerFactory(protocol.ServerFactory): 

    protocol = Echo 


factory = EchoServerFactory() 

reactor.listenTCP(...., factory) 

reactor.run() 

回答

3

至關重要的是,你總是發佈確切的代碼,你正在運行 - 您的Echo服務器將....指定爲在執行時引發語法錯誤的端口。發佈確切的代碼意味着您可以更快地獲得更好的迴應。

用一個數字替換端口,9999表示允許服務器代碼運行。現在我們可以通過telnet或netcat連接來測試服務器:

$ nc -c localhost 9999 
hello 
hello 

太棒了!服務器工作正常。請注意,當你鍵入「退出」給出了一個錯誤:

exceptions.NameError: global name 'loseConnection' is not defined 

你應該打電話self.transport.loseConnection()如果你想手動斷開連接。然後,您定義的connectionLost方法將被稱爲事件,以便您進行響應。在這個階段你並不需要定義這種方法。下面是與修改服務器代碼的修改版本建議:

from twisted.internet import reactor, protocol, stdio 
from twisted.protocols import basic 

class Echo(basic.LineReceiver): 
    print "Welcome to Chat" 

    def connectionMade(self): 
     print "A new client has connected" 

    def lineReceived(self, line): 
     print 'server received:', line 
     print 'server sent:', line, '\n' 
     self.sendLine(line) 
     if line=="exit": 
      self.transport.loseConnection() 


class EchoServerFactory(protocol.ServerFactory): 
    protocol = Echo 


factory = EchoServerFactory() 
reactor.listenTCP(9999, factory) 
reactor.run() 

客戶端具有與端口相同的問題,更改爲9999允許它運行。您的客戶端連接,但不發送任何數據。下面是發送一些文字時,延遲2秒後連接和回聲文本回服務器版本:

from twisted.internet import reactor, stdio, protocol 
from twisted.protocols import basic 

class Echo(basic.LineReceiver): 
    def connectionMade(self): 
     print "Welcome to the Chat, you have now connected" 

     # send some text when we connect 
     self.sendLine('hello') 

    def lineReceived(self, line): 
     print 'client received:', line 

     if len(line) > 10: 
      self.sendLine('exit') 
     else: 
      # send a response in 2 seconds 
      reactor.callLater(2, self.sendLine, '>' + line) 

    def connectionLost(self, reason): 
     reactor.stop() 


class EchoClientFactory(protocol.ClientFactory): 
    protocol = Echo 

factory = EchoClientFactory() 
reactor.connectTCP("localhost", 9999, factory) 
reactor.run() 

這會導致原始消息反彈,並轉發到服務器,而客戶端前添加一個>字符每次。當消息達到一定長度時,客戶端將發送「退出」消息,導致連接被服務器丟棄。當連接斷開時,客戶端可以停止其反應器,以便它退出。

輸入終端窗口不會通過客戶端向服務器發送數據 - 爲此使用telnet或netcat。

+0

你的代碼沒有工作,我只想讓他們彼此聊天,扭曲是如此混亂。 – mateus

+0

sendLine()和self.transport.write的用途是什麼?他們似乎都是在傳輸數據,但實際上只是打印到終端窗口。 dataRecieved和lineRecieved之間的區別似乎是完全相同的。我從你的代碼嘗試了rector.callLater,它不起作用。這真是令人沮喪,我越瞭解扭曲越容易混淆它,社區已經死了,所以這個可笑的小問題已經讓我過了很久。我可以編寫服務器 - 客戶端而不是扭曲,但我只是想了解它。 Errrrrrrrrrrrrrrrrrr ...... – mateus

+0

@mateus LineReceiver類擴展了基本協議類,並將'sendLine'定義爲一種方便的方法 - 它可能類似於'self.transport.write(line +'\ n')'。它還定義了'lineReceived',它只有在收到完整的行時才被調用,而基本的'Protocol'類具有'dataReceived',當你只有部分行(例如只有幾個字符)時被調用。如果您仍然想要調用'lineReceived',則不能在'LineReceiver'類中覆蓋'dataReceived'。 –