I am trying to "simulate message passing between 6 nodes in a distributed environment" using Zero MQ in Python, in particular with the classic client/server architecture with REQ and REP. My idea is, while using a TCP/IP connection between these nodes, in the first iteration node-1 must be the server and the clients are the other nodes. In the next one, node-2 will be server and the rest (including node-1) should be clients and so on. At every iteration, server tells that it has established itself and clients send requests to the server to which an acknowledgement is sent back. Once the ACK has been received, the clients send their "MESSAGE" to the server (which is of course viewed as output) and we move to the next iteration.
The problem now is that I am facing the well known ZMQError: Address already in use
I'm not sure if it's due to the socket binding. I have added a socket.close()
and context.term()
into both client and server functions, but in vain.
And when I somehow try to run the code the VM goes into deadlock and I'm unable to recover unless I perform a hard reboot. Here is a snippet of my code -
@staticmethoddef server(node_id): context = zmq.Context() socket = context.socket(zmq.REP) socket.bind("tcp://*:%s" % port_s) print "Running server node %s on port: %s and value of server = __temp__" % (node_id, port_s) message = socket.recv() print "Received request : %s from c_node %s and value (temp): __value__" % (message, c_node) socket.send("Acknowledged - from %s" % port_s) time.sleep(1) socket.close() context.term() @staticmethod def client(c_node): context = zmq.Context()# print "Server node __num__ with port %s" % port_s socket = context.socket(zmq.REQ) #for port in ports: socket.connect ("tcp://localhost:%s" % port_c)#for request in range(20): print "c_node %s Sending request to server node __num__" % c_node socket.send ("Hello") message = socket.recv() print "Received ack from server %s and message %s" % (node_id, message) time.sleep (1) socket.close() context.term() def node(self, node_id): #global node_id # global key# ser_p = Process(target=self.server, args=(node_id,)) print 'Memory content of node %d\n' % node_id for key in nodes_memory[node_id]: print 'Neighbor={%s}, Temp={%s}\n' % (key, nodes_memory[node_id][key]) #return key global c_node #key1 = key# cli_p = Process(target=self.client, args=(c_node,)) with open("Book5.csv","r+b") as input: has_header = csv.Sniffer().has_header(input.read(1024)) input.seek(0) # rewind incsv = csv.reader(input) if has_header: next(incsv) # skip header csv_dict = csv.DictReader(input, skipinitialspace=True, delimiter=",") node_id = 0 for row in csv_dict: for i in row: #print(row[i]) if type(row[i]) is str: g.add_edge(node_id, int(i), conn_prob=(float(row[i]))) max_wg_ngs = sorted(g[node_id].items(), key=lambda e: e[1]["conn_prob"], reverse=True)[:2] #maxim = max_wg_ngs.values.tolist() #sarr = [str(a) for a in max_wg_ngs] print "\nNeighbours of Node %d are:" % node_id #print(max_wg_ngs) ser_p = multiprocessing.Process(target=self.server, args=(node_id,)) ser_p.start() for c_node, data in max_wg_ngs: for key in nodes_memory[node_id]: #print ''.join(str(item))[1:-1] #if type(key1) == node_id: cli_p = multiprocessing.Process(target=self.client, args=(c_node,)) cli_p.start() print('Node {a} with Connection Rate = {w}'.format(a=c_node, w=data['conn_prob'])) print('Temperature of Node {a} = {b}'.format(a=c_node, b=nodes_memory[node_id][key])) node_id += 1 pos=nx.spring_layout(g, scale=100.) nx.draw_networkx_nodes(g, pos) nx.draw_networkx_edges(g,pos) nx.draw_networkx_labels(g,pos) #plt.axis('off') #plt.show()
The "message" is "temperature" (file not shown in the code snippet, but not needed at the moment) and for reference the values of Book5.csv
are -0,1,2,3,4,50,0.257905291,0.775104118,0.239086843,0.002313744,0.4169366030.346100279,0,0.438892758,0.598885794,0.002263231,0.4066852370.753358102,0.222349243,0,0.407830809,0.001714776,0.5075735920.185342928,0.571302688,0.51784403,0,0.003231018,0.2951975330,0,0,0,0,00.478164621,0.418192795,0.646810223,0.410746629,0.002414973,0
ser_p
and cli_p
are objects for the server and client functions which are called in the node
function, i.e ser_p
is called in the loop for row in csv_dict
and cli_p
is called even further in for c_node, data in max_wg_ngs
. I'm using Networkx Python library here as well (Only to find 2 nearest neighbours out of the clients using the connection probability values from Book5.csv
).
Does anyone know where I might be going wrong? Why is it that it shows address is already in use even though the socket is closed at every iteration?
Thanks a lot in advance :) (Using Ubuntu 14.04 32-bit VM)