I'm writing a small socket server to wrap around a .NET/C# API. I'm having trouble to get it to work when the SocketServer runs under IronPython. I'm using version 2.7.4.
When I run the server like this:
C:\Python27\python.exe data_server.py
From the client I get the output I expect:
C:\Python27\python.exe data_client.py
{'host': ('localhost', 31337), 'name': 'A'}
{'host': ('localhost', 31337), 'name': 'B'}
{'host': ('localhost', 31337), 'name': 'C'}
But when I run the server using IronPython, I get nothing from the client. I.e.
"C:\Program Files (x86)\IronPython 2.7\ipy64.exe" ipdb_server.py
I have tried 32/64bit IronPython and running the client with 32/64 bit IronPython. Whatever way I do it, the IronPython server doesn't seem to work.
Any ideas what I'm doing wrong?
The server code looks like this:
# data_server.py
import sys, os, pickle, SocketServer
PORT = 31337
def dump_data(f):
for w in ['A','B','C']: # test data to be replaced by call to .NET API
meta = {}
meta['name'] = w
print 'Sending: ', meta
pickle.dump(meta, f)
class DataHandler(SocketServer.BaseRequestHandler):
def handle(self):
f = self.request.makefile()
dump_data(f)
f.close()
SocketServer.TCPServer.allow_reuse_address = True
serv = SocketServer.TCPServer(("",PORT), DataHandler)
print "server running on port %d" % PORT
serv.serve_forever()
The client code looks like this:
# data_client
import pickle, socket
def get_data(host):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(host)
f = s.makefile()
try:
while True:
meta = pickle.load(f)
meta['host'] = host
yield meta
except EOFError:
pass
f.close()
s.close()
data = get_data(("localhost",31337))
for d in data: print d
I think I can answer my own question. It turns out that I had to change the call to socket.makefile to explicitly specify binary mode. I.e.:
f = self.request.makefile('b')
I assume that this is down to a subtly different implementation in IronPython.