【问题标题】:Client - Server Chat in Twisted, Python [closed]客户端-Twisted,Python中的服务器聊天[关闭]
【发布时间】:2014-01-07 02:07:51
【问题描述】:

当服务器和客户端都位于不同的终端窗口时,我无法让它们进行通信。我可以让它们都连接,但实际上并没有将它们的输出发送到彼此的 windows.I 客户:

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()

【问题讨论】:

    标签: python twisted


    【解决方案1】:

    始终发布您正在运行的确切代码至关重要 - 您的 Echo 服务器将 .... 指定为在执行时引发语法错误的端口。发布确切的代码意味着您可以更快地获得更好的响应。

    用数字替换端口,9999 表示允许服务器代码运行。现在我们可以通过 telnet 或 netcat 连接来测试服务器:

    $ nc -c localhost 9999
    hello
    hello
    

    太棒了!服务器工作正常。请注意,当您键入“exit”时会报错:

    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。

    【讨论】:

    • 你的代码不行,我只想让他们互相聊天,twisted 太混乱了。
    • sendLine() 和 self.transport.write 的目的是什么?它们看起来都像是在传输数据,但实际上只是打印到终端窗口。 dataRecieved 和 lineRecieved 之间的区别是什么,它们似乎都做同样的事情。我从您的代码中尝试了rect.callLater,但它没有用。这真的很令人沮丧,我对扭曲的了解越多,它就越混乱,而且社区已经死了,所以这个可笑的小问题花了我很多时间。我可以不用扭曲地编写服务器客户端,但我只想学习它。 Errrrrrrrrrrrrrrrrrr……
    • @mateus LineReceiver 类扩展了基础协议类并将sendLine 定义为一种方便的方法——它可能类似于self.transport.write(line + '\n')。它还定义了lineReceived,仅在收到完整行时调用,而基类Protocol 具有dataReceived,当您可能只有部分行(例如,只有几个字符)时调用。如果您仍希望调用 lineReceived,则不能在 LineReceiver 类中覆盖 dataReceived
    • @mateus 究竟什么不适合你,你期望发生什么 - 它在这里有效
    • @mateus,哦,您期待聊天功能吗? sendLineself.transport.write 仅将数据发送回该连接的客户端。如果您想向其他客户端发送消息,请查看twistedmatrix.com/documents/current/core/examples/#auto1
    猜你喜欢
    • 2015-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多