I’m tired of testing the data transmission between computers. I’ve created at home a simple local network on the basis of wifi with two ip-addresses and opened ports 5555, via which the nodes will work.
The server (working node or masternode) listens to everything that arrives at port 5555
from random import randint
import time
import zmq
import sys
from cl_node import *
node = Node()
context = zmq.Context(1)
server = context.socket(zmq.REP)
server.bind("tcp://*:5555")
cycles = 0
while True:
request_clear = server.recv()
request = eval(request_clear.decode())
if 'wtf' in request:
print('Work on new transaction')
print(cycles, ": Normal request (%s)" % str(request))
if 'addmeplz' in request:
print('Try add new node')
node.add_new_node(request['adr'],request['ip'])
print(cycles, ": Normal request (%s)" % str(request))
cycles += 1
# Simulate various problems, after a few cycles
if cycles > 1000 and randint(0, 1000) == 0:
print("I: Simulating a crash")
break
elif cycles > 1000 and randint(0, 100) == 0:
print("I: Simulating CPU overload")
time.sleep(2)
#time.sleep(1) # Do some heavy work
send_hash = node.thishash(request_clear).encode()
print(send_hash)
server.send(send_hash)
server.close()
context.term()
In this code, we use zeroMQ to get a message on the port, and if there is a code in the message - addmeplz, then we will add a new node to the list of nodes that are responsible for the consensus.
And this is a client who is knocking on the network to join the ranks of the nodes:
context = zmq.Context(1)
client = context.socket(zmq.REQ)
SERVER_ENDPOINT = 'tcp://'+base_node
client.connect(SERVER_ENDPOINT)
poll = zmq.Poller()
poll.register(client, zmq.POLLIN)
REQUEST_TIMEOUT = 2500
REQUEST_RETRIES = 3
retries_left = REQUEST_RETRIES
while retries_left:
data_send = {'addmeplz': '1','adr': adr, 'ip': ipport}
data_send = str(data_send).encode()
request = data_send
print("I: Пepecылaю (%s)" % request)
client.send(request)
expect_reply = True
while expect_reply:
socks = dict(poll.poll(REQUEST_TIMEOUT))
if socks.get(client) == zmq.POLLIN:
reply = client.recv()
print(reply)
print(self.thishash(request))
if not reply:
break
if reply.decode() == self.thishash(request):
print("I: Server replied OK (%s)" % reply)
retries_left = 0
data = 'server get you request'
expect_reply = False
else:
print("E: Malformed reply from server: %s" % reply)
else:
print("W: No response from server, retrying…")
# Socket is confused. Close and remove it.
client.setsockopt(zmq.LINGER, 0)
client.close()
poll.unregister(client)
retries_left -= 1
if retries_left == 0:
print("E: Server seems to be offline, abandoning")
break
print("I: Reconnecting and resending (%s)" % request)
# Create new connection
client = context.socket(zmq.REQ)
client.connect(SERVER_ENDPOINT)
poll.register(client, zmq.POLLIN)
client.send(request)
return str(data)
In this case, this is the method that gets the address (node public address), ip and port of the future node (ip should be static), and base_node, this is the address that we are knocking on.
Then it is necessary for the server (masternode) after receiving the message to add a new node to the file with a list of working nodes (the vector of active nodes) and send it to all other nodes for consensus in the list of active nodes (or the vector of active nodes).