3

I am writing a simple command line chat program with the Twisted framework. In three separate command lines I have opened my chat server and two clients (see code below).

The problem I am having is that if I send a message from one client the next client won't receive it. However once that other client sends its own message it receives the message from the other client. Hope this is clear.

Thanks

Server:

from twisted.protocols import basic

class MyChat(basic.LineReceiver):
    def connectionMade(self):
        print "Got new client!"
        self.factory.clients.append(self)

    def connectionLost(self, reason):
        print "Lost a client!"
        self.factory.clients.remove(self)

    def lineReceived(self, line):
        data = repr(line)
        print data
        for c in self.factory.clients:
            c.message(data)

    def message(self, message):
        self.transport.write(message + '\r\n')



from twisted.internet import reactor, protocol
from twisted.application import service, internet

factory = protocol.ServerFactory()
factory.protocol = MyChat
factory.clients = []
reactor.listenTCP(8042, factory)
reactor.run()

Client:

from twisted.protocols import basic


# a client protocol

class EchoClient(basic.LineReceiver):

    def sendData(self):
        data = raw_input("> ")
        if data:
            print "sending %s...." % data
            self.transport.write(data + "\r\n")
        else:
            self.transport.loseConnection()

    def connectionMade(self):
        self.username = raw_input("Name: ")
        self.sendData()

    def lineReceived(self, data):
        print data
        self.sendData()

    def connectionLost(self, reason):
        print "connection lost"

class EchoFactory(protocol.ClientFactory):
    protocol = EchoClient

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

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


# this connects the protocol to a server runing on port 8000
def main():
    f = EchoFactory()
    reactor.connectTCP("localhost", 8042, f)
    reactor.run()

# this only runs if the module was *not* imported
if __name__ == '__main__':
    main()
Jay Jen
  • 705
  • 1
  • 7
  • 11
  • it most probably has to do with buffer. you may try to: 1. flush the buffer after each send. 2. decrease buffer size.(not optimal solution) 3. send EOF or equivalent in python(it often triggers flush) – Kamyar Ghasemlou Jan 29 '15 at 14:09

1 Answers1

1

Your sendData is blocking. You can think of Twisted as a big while True loop that checks each cycle whether or not there are things to do. So once you enter the sendData function and call raw_input you in effect are stopping your whole program.

Have a look at this question

Community
  • 1
  • 1
Sjuul Janssen
  • 1,772
  • 1
  • 14
  • 28
  • Thanks for your answer. So do you suggest not using Twisted then for my client? If so can I still use Twisted for my server? – Jay Jen Jan 29 '15 at 14:56
  • Twisted is fine for your client. There are ways to get input from your program other than `raw_input`. In fact, even if you're not using Twisted, `raw_input` is a bad idea for a chat program, since the output will corrupt the input line that you're editing! https://github.com/twisted/imaginary has a good example of a setup which might be appropriate for a chat program - have a look at https://github.com/twisted/imaginary/blob/master/imaginary/__main__.py for more information. – Glyph Jan 30 '15 at 01:49