Client - Server Chat in Twisted, Python [closed] - python

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I can't get the Server and Client to communicate when they are both in different terminal windows. I can get them to both connect though not actually send their output to each others windows.I
Client:
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()
Server:
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()

It is vital that you always post the exact code that you are running - your Echo Server specifies .... as the port which raises a syntax error on execution. Posting the exact code will mean you get better responses faster.
Replacing the port with a number, 9999 say allows the server code to run. Now we can connect via telnet or netcat to test the server:
$ nc -c localhost 9999
hello
hello
Great! The server works fine. Note that it gives an error when you type "exit":
exceptions.NameError: global name 'loseConnection' is not defined
You should be calling self.transport.loseConnection() if you want to drop the connection manually. The connectionLost method you've defined is then called as an event to allow you to respond. You don't really need to define that method at this stage. Here is a modified version of your server code with the changes suggested:
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()
The client has the same problem with the port, changing to 9999 allows it to run. Your client connects, but then does not send any data. Here's a version that sends some text when it connects and echos text back to the server after a 2 second delay:
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()
This causes the original message to bounce back and forwards to the server, while the client prepends a > character each time. The client will then send "exit" when the message gets to a certain length, causing the connection to be dropped by the server. When the connection is dropped, the client can stop its reactor so that it exits.
Typing into the terminal window does not send data through your client to the server - use telnet or netcat for this purpose.

Related

Twisted close web server connection

Im writing a simple web server application using twisted. The application will get a string and return the reverse of the string it received.
It all works fine. Now I need to close the socket connection if there is an inactivity for 5 mins.
Here is my server code:-
from twisted.internet import reactor, protocol
class Echo(protocol.Protocol):
"""This is just about the simplest possible protocol"""
def dataReceived(self, data):
"As soon as any data is received, write it back."
self.transport.write(data[::-1])
def main():
"""This runs the protocol on port 8000"""
factory = protocol.ServerFactory()
factory.protocol = Echo
reactor.listenTCP(8000,factory)
reactor.run()
# this only runs if the module was *not* imported
if __name__ == '__main__':
main()
~
Add these methods to your class:
def connectionMade(self):
def terminate():
self.terminateLater = None
self.transport.abortConnection()
self.terminateLater = reactor.callLater(60 * 5, terminate)
def connectionLost(self, reason):
delayedCall = self.terminateLater
self.terminateLater = None
if delayedCall is not None:
delayedCall.cancel()
This makes it so that when a connection is established, your protocol will scheduled a timed call in 5 minutes to close the connection. If the connection is closed otherwise, it will cancel the timeout.

Socket disconnected after a message, (Connection refused by remote host), using python

I have uploaded my python socket, (cloud service project), on azure ,and when ever I connected to Hercules client side socket ....after a message or two, connection closed by remote host... forcefully...?
Server Code
from twisted.internet.protocol import Factory, Protocol
from twisted.internet import reactor
import SocketServer
class IphoneChat(Protocol):
def connectionMade(self):
self.factory.clients.append(self)
print('clients are'), self.factory.clients
def connectionLost(self, reason):
self.factory.clients.remove(self)
def dataReceived(self, data):
msg = ""
msg = data.strip()
for c in self.factory.clients:
c.message(msg)
def message(self, message):
self.transport.write(message + '\n')
print ('Iphone Chat server startedd')
factory = Factory()
factory.protocol = IphoneChat
factory.clients = []
reactor.listenTCP(9073, factory)
reactor.run()
I tried to reproduce your issue on my environment, but failed. Base on my experience, we often pay attention to 3 points if we use socket in azure worker role.
Open input TCP port. If we open a port as listener port, we'd better to add this port into the endpoints setting.
Considered the worker role status, I suggest we can code logic into the while True loop function, as following,
while True:
reactor.listenTCP(65534, f)
print "server run"
reactor.run()
sleep(1.0)
According to the error message, I guess the reason is that azure load balancer will kill the idle connection in 240s. I recommend you can refer to this blog to configure your idleTimeoutInMinutes value.
Please try to check your project and configuration. Any further findings, please let me know.

How to detect the server closing a unix domain socket?

I'm messing around with the python twisted library, and I can't seem to figure out how to get my client to detect a server closing its socket. My client continues to let me send data to the non existent server. Here is my server:
test_server.py
from twisted.internet import protocol, reactor, endpoints, stdio
from twisted.protocols.basic import LineReceiver
class ConnectionProtocol(LineReceiver):
from os import linesep as delimiter
def lineReceived(self, line):
print 'got line: %s' % line
self.sendLine(line)
class ConnectionFactory(protocol.Factory):
def buildProtocol(self, addr):
return ConnectionProtocol()
def main():
endpoint = endpoints.UNIXServerEndpoint(reactor, './test.sock', 5, 0777, False)
endpoint.listen(ConnectionFactory())
print 'starting the reactor'
reactor.run()
main()
All it does is send each line it gets back to the connecting client.
Here is the client:
test_client.py
import os
from twisted.internet import protocol, reactor, endpoints, stdio
from twisted.protocols.basic import LineReceiver
class CommandProtocol(protocol.Protocol):
def dataReceived(self, data):
print data,
class StdinProtocol(LineReceiver):
from os import linesep as delimiter
def __init__(self, client):
self._client = client
def connectionMade(self):
self.transport.write('>>> ')
def lineReceived(self, line):
print 'writing line: %s' % line
self._client.transport.write(line + os.linesep)
def printError(failure):
print str(failure)
def main():
point = endpoints.UNIXClientEndpoint(reactor, './test.sock')
proto = CommandProtocol()
d = endpoints.connectProtocol(point, proto)
d.addErrback(printError)
stdio.StandardIO(StdinProtocol(proto))
reactor.run()
main()
If I run the server and then the client, and then kill the server, the client still writes to the CommandProtocol's transport like nothing happened. I thought the errback function would at least report something. In the case where the client is run before the server, the errback function is called with a ConnectError, but I'm specifically looking to detect the situation where the client has already connected to a server, and the server exits.
How can I detect that the server has shutdown?
ITransport.write is a silent no-op if called on a transport that has been disconnected.
If you want to learn that a connection was lost, override the connectionLost method. Once you know that the connection has been lost you can arrange for your program to stop accepting input or do something else with the input it receives.
i guess os.stat method and stat module can help you. Can you change your client codes to like below:
import os
import stat
from twisted.internet import protocol, reactor, endpoints, stdio
from twisted.protocols.basic import LineReceiver
class CommandProtocol(protocol.Protocol):
def dataReceived(self, data):
print data,
class StdinProtocol(LineReceiver):
from os import linesep as delimiter
def __init__(self, client):
self._client = client
def connectionMade(self):
self.transport.write('>>> ')
def lineReceived(self, line):
print 'writing line: %s' % line
self._client.transport.write(line + os.linesep)
def printError(failure):
print str(failure)
def main():
if os.stat('./test.sock').st_mode & (stat.S_IRGRP | stat.S_IRUSR | stat.S_IROTH):
print "1"
print "using control socket"
point = endpoints.UNIXClientEndpoint(reactor, './test.sock')
proto = CommandProtocol()
d = endpoints.connectProtocol(point, proto)
d.addErrback(printError)
stdio.StandardIO(StdinProtocol(proto))
reactor.run()
else:
print "not ready"
main()

How to manage connections and Clients in Twisted?

I started working with Twisted Framework, I wrote a TCP server and I connect to it throw Telnet, it works fine. Now I want to manage connections and connected clients( sending data, cutting connections, etc etc) using an GUI like PyUI or GTK..
this is my code
import sys
import os
from twisted.internet import reactor, protocol
from twisted.python import log
class Server(protocol.Protocol):
def dataReceived(self, data):
log.msg ("data received: %s"%data)
self.transport.write("you sent: %s"%data)
def connectionMade(self):
self.client_host = self.transport.getPeer().host
self.client_port = self.transport.getPeer().port
if len(self.factory.clients) >= self.factory.clients_max:
log.msg("Too many connections !!")
self.transport.write("Too many connections, sorry\n")
self.transport.loseConnection()
else:
self.factory.clients.append((self.client_host,self.client_port))
log.msg("connection from %s:%s\n"%(self.client_host,str(self.client_port)))
self.transport.write(
"Welcome %s:%s\n" %(self.client_host,str(self.client_port)))
def connectionLost(self, reason):
log.msg('Connection lost from %s:%s. Reason: %s\n' % (self.client_host,str(self.client_port),reason.getErrorMessage()))
if (self.client_host,self.client_port) in self.factory.clients:
self.factory.clients.remove((self.client_host,self.client_port))
class MyFactory(protocol.ServerFactory):
protocol = Server
def __init__(self, clients_max=10):
self.clients_max = clients_max
self.clients = []
def main():
"""This runs the protocol on port 8000"""
log.startLogging(sys.stdout)
reactor.listenTCP(8000,MyFactory)
reactor.run()
if __name__ == '__main__':
main()
Thanks.
If you want to write a single Python program (process) that runs both your UI and your networking, you will first need to choose an appropriate Twisted reactor that integrates with the UI toolkit's event loop. See here.
Next, you might start with something simple, like have a button that when pressed will send a text message to all currently connected clients.
Another thing: what clients will connect? Browsers (also)? If so, you might contemplate about using WebSocket instead of raw TCP.

Twisted client for a send only protocol that is tolerant of disconnects

I've decided to dip my toe into the world of asynchronous python with the help of twisted. I've implemented some of the examples from the documentation, but I'm having a difficult time finding an example of the, very simple, client I'm trying to write.
In short I'd like a client which establishes a tcp connection with a server and then sends simple "\n" terminated string messages off of a queue object to the server. The server doesn't ever respond with any messages so my client is fully unidirectional. I /think/ that what I want is some combination of this example and the twisted.internet.protocols.basic.LineReceiver convenience protocol. This feels like it should be just about the simplest thing one could do in twisted, but none of the documentation or examples I've seen online seem to fit quite right.
What I have done is not used a Queue but I am illustrating the code that sends a line, once a connection is made. There are bunch of print stuff that will help you understand on what is going on.
Usual import stuff:
from twisted.web import proxy
from twisted.internet import reactor
from twisted.internet import protocol
from twisted.internet.protocol import ReconnectingClientFactory
from twisted.protocols import basic
from twisted.python import log
import sys
log.startLogging(sys.stdout)
You create a protocol derived from line receiver, set the delimiter.
In this case, I simply write a string "www" once the connection is made.
The key thing is to look at protocol interface at twisted.internet.interface.py and understand the various methods of protocol and what they do and when they are called.
class MyProtocol(basic.LineReceiver):
#def makeConnection(self, transport):
# print transport
def connectionLost(self, reason):
print reason
self.sendData = False
def connectionMade(self):
print "connection made"
self.delimiter = "\n"
self.sendData = True
print self.transport
self.sendFromQueue()
def sendFromQueue(self):
while self.sendData:
msg = dataQueue.get()
self.sendLine(msg)
# you need to handle empty queue
# Have another function to resume
Finally, A protocol factory that will create a protocol instance for every connection.
Look at method : buildProtcol.
class myProtocolFactory():
protocol = MyProtocol
def doStart(self):
pass
def startedConnecting(self, connectorInstance):
print connectorInstance
def buildProtocol(self, address):
print address
return self.protocol()
def clientConnectionLost(self, connection, reason):
print reason
print connection
def clientConnectionFailed(self, connection, reason):
print connection
print reason
def doStop(self):
pass
Now you use a connector to make a connection:
reactor.connectTCP('localhost', 50000, myProtocolFactory())
reactor.run()
I ran this and connected it to an server that simply prints what it receives and hence send no ack back. Here is the output:
1286906080.08 82 INFO 140735087148064 __main__ conn_made: client_address=127.0.0.1:50277
1286906080.08 83 DEBUG 140735087148064 __main__ created handler; waiting for loop
1286906080.08 83 DEBUG 140735087148064 __main__ handle_read
1286906080.08 83 DEBUG 140735087148064 __main__ after recv
'www\n'
Recieved: 4
The above example if not fault tolerant. To reconnect , when a connection is lost, you can derive your protocol factory from an existing twisted class - ReconnectingClientFactory.
Twisted has almost all the tools that you would need :)
class myProtocolFactory(ReconnectingClientFactory):
protocol = MyProtocol
def buildProtocol(self, address):
print address
return self.protocol()
For further reference
I suggest that you read : http://krondo.com/?page_id=1327
[Edited: As per comment below]

Categories