2

I'm trying to build a client/server system that clients send messages to server. Server does nothing more than printing out what clients send.

from twisted.internet import protocol, reactor

class Echo(protocol.Protocol):
    def dataReceived(self, data):
        print data
        self.transport.write(data)

class EchoFactory(protocol.Factory):
    def buildProtocol(self, addr):
        return Echo()

reactor.listenTCP(8000, EchoFactory())
reactor.run()

The issue is that when I tried to send multiple message from client with this code, the client raises an error after the first connection and send.

from twisted.internet import reactor, protocol
import time

class EchoClient(protocol.Protocol):
   def __init__(self, message):
       self.message = message

   def connectionMade(self):
       self.transport.write(self.message)

   def dataReceived(self, data):
       print "Server said:", data
       self.transport.loseConnection()

class EchoFactory(protocol.ClientFactory):
   def __init__(self, message):
       self.message = message

   def buildProtocol(self, addr):
       return EchoClient(self.message)

   def clientConnectionFailed(self, connector, reason):
       print "Connection failed."
       reactor.stop()

   def clientConnectionLost(self, connector, reason):
       print "Connection lost."
       reactor.stop()

def sendMessage(message):
    reactor.connectTCP("localhost", 8000, EchoFactory(message))
    reactor.run()

if __name__ == "__main__":
    while True:
        r = raw_input(">")
        if r == 'q' or len(r) == 0: break
        sendMessage(r)

What might be wrong? this is the error message.

>a
Server said: a
Connection lost.
>b
Traceback (most recent call last):
  File "echoclient.py", line 38, in <module>
    sendMessage(r)
  File "echoclient.py", line 32, in sendMessage
    reactor.run()
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/twisted/internet/base.py", line 1168, in run
    self.startRunning(installSignalHandlers=installSignalHandlers)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/twisted/internet/base.py", line 1148, in startRunning
    ReactorBase.startRunning(self)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/twisted/internet/base.py", line 680, in startRunning
    raise error.ReactorNotRestartable()
twisted.internet.error.ReactorNotRestartable
prosseek
  • 182,215
  • 215
  • 566
  • 871

3 Answers3

2

Although this question is old and has two irrelevant answers, I would like to answer it for the people who are eager to know. The problem is that in your server code in the dataReceived method you have self.transport.write(data) (which sends every message that it receives to the client), and at the same time in your client code, again in the dataReceived method you have the command self.transport.loseConnection() (which looses the connection to the server as soon as a message comes in). So, if you remove any of these lines you should be fine. In the current setting the first message sent from client will be sent back to the client and that will cause a connection disconnect.

Also, you are calling reactor.run () at each attempt for sending a message. Reactor.run should be called only once preferably in the main function.

user823743
  • 2,152
  • 3
  • 21
  • 31
0

The reactor is not restartable.

Jean-Paul Calderone
  • 47,755
  • 6
  • 94
  • 122
  • Then, what might be used for interactive communication that requires multiple message sending between client and server with twisted? – prosseek Feb 26 '14 at 14:26
  • 1
    Call `raw_input` if you want. It blocks and will prevent your application from servicing events while doing so but if you don't mind that then it will work just fine (and it's no worse than what you've written, plus it won't fail with `ReactorNotRestartable` exceptions). Otherwise, if you want to service network and stdio events concurrently, look at `twisted.internet.stdio`. – Jean-Paul Calderone Feb 26 '14 at 15:20
-1

For my own purposes, using socket to send messages to server works fine.

import socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('localhost', 8000))
while True:
    a = raw_input("> ")
    if a == 'q' or len(a) == 0: 
        client_socket.close()
        break
    else:
        client_socket.send(a)
prosseek
  • 182,215
  • 215
  • 566
  • 871