I am writing a Python module which is communicating with a go program through unix sockets. The client (the python module) write data to the socket and the server consume them.
# Simplified version of the code used
outputStream = socket.socket(socketfamily, sockettype, protocol)
outputStream.connect(socketaddress)
outputStream.setblocking(True)
outputStream.sendall(message)
....
outputStream.close()
My issue is that the Python client tends to finish and close the socket before the data have been effectively read by the server which leads to a "broken pipe, connection reset by peer" on the server side. Whatever I do, for the Python code everything has been sent and so the calls to send() sendall() select() are all successful...
Thanks in advance
EDIT: I can't use shutdown because of mac OS
EDIT2: I also tried to remove the timeout and call setblocking(True) but it doesn't change anything
EDIT3: After ready this issue http://bugs.python.org/issue6774 it seems that the documentation is unnecessary scary so I restored the shutdown but I still have the same issue:
# Simplified version of the code used
outputStream = socket.socket(socketfamily, sockettype, protocol)
outputStream.connect(socketaddress)
outputStream.settimeout(5)
outputStream.sendall(message)
....
outputStream.shutdown(socket.SHUT_WR)
outputStream.close()
IHMO this is best done with an Asynchornous I/O library/framework. Here's such a solution using circuits:
The server echos what it receives to stdout and the client opens a file and sends this to the server waiting for it to complete before closing the socket and terminating. This is done with a mixture of Async I/O and Coroutines.
server.py:
from circuits import Component
from circuits.net.sockets import UNIXServerclass Server(Component):def init(self, path):UNIXServer(path).register(self)def read(self, sock, data):print(data)Server("/tmp/server.sock").run()
client.py:
import sysfrom circuits import Component, Event
from circuits.net.sockets import UNIXClient
from circuits.net.events import connect, close, writeclass done(Event):"""done Event"""class sendfile(Event):"""sendfile Event"""class Client(Component):def init(self, path, filename, bufsize=8192):self.path = pathself.filename = filenameself.bufsize = bufsizeUNIXClient().register(self)def ready(self, *args):self.fire(connect(self.path))def connected(self, *args):self.fire(sendfile(self.filename, bufsize=self.bufsize))def done(self):raise SystemExit(0)def sendfile(self, filename, bufsize=8192):with open(filename, "r") as f:while True:try:yield self.call(write(f.read(bufsize)))except EOFError:breakfinally:self.fire(close())self.fire(done())Client(*sys.argv[1:]).run()
In my testing of this it behaves exactly as I expect it to with noerrors and the servers gets the complete file before the client clsoesthe socket and shuts down.