I have program which has servers interacting with each other using Twisted's remote procedure calls, and I run in problems with closing connections when they are not needed anymore. Connections should be able to close itself in both sides.
Case 1: How do I close connection in connecting part?
factory = pb.PBClientFactory()
reactor.connectTCP(ip, port, factory)
deferred = factory.login(credentials.UsernamePassword(username, password), client=self)
deferred.addCallbacks(self.connectedToServer, self.errorConnectingToServer)
def connectedToServer(self, server):
self.server = server
# Closing connection comes here
Case 2: How do I close connection in server part?
class MyPerspective(pb.Avatar):
def connected(self, server):
self.client = server
# Closing connection comes here
At the moment I use raising pb.Error() to close connection, but I don't think that's the proper way to do it.
Another option is reference.broker.transport.loseConnection().
RemoteReference instances which are created over a PB connection are given a broker attribute. The broker attribute refers to the protocol instance that created them. As usual for a protocol, the broker has a transport attribute, and the transport has a loseConnection method.
Related
I have quite a complex TCP/IP server that connects to several clients. I was running into an issue where my clients were not being updated that the socket was closing. I believe I need to call both socket.shutdown() and socket.close() to be able send a server closing advisory to all of the clients. However, I get an OS error whenever I call socket.shutdown().
OSError: [WinError 10057] A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
Does anybody know why this is happening? Or some other way of closing the socket while still sending the advisory to all connected clients? I could always write a custom command that resets all of the clients before calling socket.close(), but something seems wrong with my server. Below is minimum reproducible example.
import socket
import selectors
class server_test:
host = ''
port = 12345
sel = selectors.DefaultSelector()
def __init__(self):
self.start_server()
self.stop_server()
#Server Functions
def start_server(self):
self.lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.lsock.bind((self.host, self.port))
self.lsock.listen()
print("Server starting, listening on ",. (self.host, self.port))
self.lsock.setblocking(False)
self.sel.register(self.lsock, selectors.EVENT_READ, data=None)
def stop_server(self):
print("Shutting server down")
self.lsock.shutdown(1)
self.lsock.close()
I believe I need to call both socket.shutdown() and socket.close() to be able send a server closing advisory to all of the clients.
No. A shutdown(1) on a connected socket will send a FIN to the peer to signal that the local system will not send more data, but it might actually accept more data. A shutdown(0) will stop receiving data locally and reject any data send by the peer. A close() essentially combines a shutdown(1) and a shutdown(0).
self.lsock.listen()
...
self.lsock.shutdown(1)
You are trying to tell the peer of self.lsock that you will no longer send data. But self.lsock is the local listener socket which is not itself connected and thus has no peer. Since you are thus try to do an operation which requires a connected socket on a socket which is not connected (only listening) it will result in the error "... socket is not connected ...".
If you want to shutdown the connection to all clients you actually have to call shutdown or close on all connected sockets (i.e. result from self.lsock.accept() and not on the listener socket.
I have a very simple Python (Flask socket.io) application which works as a server and another app written in AngularJS which is a client.
In order to handle connected and disconnected client I use respectlivy:
#socketio.on('connect')
def on_connect():
print("Client connected")
#socketio.on('disconnect')
def on_disconnect():
print("Client disconnected")
When Client connects to my app I get information about it, in case if client disconnect (for example because of problems with a network) I don't get any information.
What is the proper way to handle the situation in which client disconnects unexpectedly?
There are two types of connections: using long-pooling or WebSocket.
When you use WebSocket clients knows instantly that server was disconnected.
In the case of long-polling, there is need to set ping_interval and pint_timeout parameters (I also find information about heartbeat_interval and heartbeat_timeout but I don't know how they are related to ping_*).
From the server perspective: it doesn't know that client was disconnected and the only way to get that information is to set ping_interval and ping_timeout.
I am implementing a tornado socket server based on this code:
https://gist.github.com/robcowie/974695
Client is Python simple socket client. When I call socket.close() in client, nothing happens in server. I put full print traces in the server and closing is not detected nowhere.
I know I can detect the closure for example sending a string "CNNDEND" which means closing. But I wonder if there is any way to detect on server socket.close() from client.
in Connection __init__:
self.stream.set_close_callback(self.__onClose)
in Connection class:
def __onClose(self):
print 'close detected'
I'm doing a python script that writes some data to a mongodb.
I need to close the connection and free some resources, when finishing.
How is that done in Python?
Use close() method on your MongoClient instance:
client = pymongo.MongoClient()
# some code here
client.close()
Cleanup client resources and disconnect from MongoDB.
End all server sessions created by this client by sending one or more endSessions commands.
Close all sockets in the connection pools and stop the monitor threads.
The safest way to close a pymongo connection would be to use it with 'with':
with pymongo.MongoClient(db_config['HOST']) as client:
db = client[ db_config['NAME']]
item = db["document"].find_one({'id':1})
print(item)
Adding to #alexce's answer, it's not always true. If your connection is encrypted, MongoClient won't reconnect:
def close(self):
...
if self._encrypter:
# TODO: PYTHON-1921 Encrypted MongoClients cannot be re-opened.
self._encrypter.close()
also, since version 4.0, after calling close() client won't reconnect in any case.
def close(self) -> None:
"""Cleanup client resources and disconnect from MongoDB.
End all server sessions created by this client by sending one or more
endSessions commands.
Close all sockets in the connection pools and stop the monitor threads.
.. versionchanged:: 4.0
Once closed, the client cannot be used again and any attempt will
raise :exc:`~pymongo.errors.InvalidOperation`.
This is a follow-up to my previous question.
I am building a simple client server program using ´twisted´ package in Python.
I would like to keep a record of which client has joined and closed the connection.
Suppose, if Client B closes the connection, I would like to print at the server "Client B has closed the connection"
Here is the code I am using :
factory = protocol.ServerFactory()
factory.protocol = Echo
PortNo = 8000
reactor.listenTCP(PortNo,factory)
reactor.run()
def connectionLost(self, reason):
print "Connection lost"
Any idea how to do it ?
Thanks
The connection which was lost is the one associated with the protocol instance referenced by the self argument to connectionLost.
With a normal factory (like ServerFactory, as you are using) there is a one to one relationship between connections and protocol instances.