158 lines
5.2 KiB
Python
158 lines
5.2 KiB
Python
|
import datetime
|
|||
|
import random
|
|||
|
|
|||
|
import zmq
|
|||
|
import threading
|
|||
|
import json
|
|||
|
import os
|
|||
|
import time
|
|||
|
import blockchain as chain
|
|||
|
|
|||
|
_basepath = os.path.abspath(os.path.dirname(__file__))
|
|||
|
conf = json.load(open(os.path.abspath(os.path.dirname(__file__)) + "\\config.json"))
|
|||
|
|
|||
|
lock = threading.Lock()
|
|||
|
|
|||
|
|
|||
|
def build_msg(cmd, msg):
|
|||
|
data = {
|
|||
|
"cmd": cmd,
|
|||
|
"msg": msg
|
|||
|
}
|
|||
|
return data
|
|||
|
|
|||
|
|
|||
|
class ZmqServer(object):
|
|||
|
def __init__(self):
|
|||
|
self.server = conf["server"]
|
|||
|
self.calc_port = conf["calc_port"]
|
|||
|
self.add_port = conf["add_port"]
|
|||
|
self.signal_port = conf["signal_port"]
|
|||
|
self.client_num = conf["client_num"]
|
|||
|
self.chain = chain.BlockChain()
|
|||
|
print("服务器初始化的链id:%s" % id(self.chain))
|
|||
|
self.ops_list = []
|
|||
|
self.uncalc_ops = []
|
|||
|
self.proof_list = []
|
|||
|
|
|||
|
def add_ops(self, option):
|
|||
|
with lock:
|
|||
|
self.ops_list.append(option)
|
|||
|
|
|||
|
def publish_calc_task(self):
|
|||
|
while True:
|
|||
|
|
|||
|
self.uncalc_ops = list(self.ops_list)
|
|||
|
print("未计算的缓存操作列表:%s"%self.uncalc_ops)
|
|||
|
print("待计算的操作列表:%s"%self.ops_list)
|
|||
|
if len(self.uncalc_ops) > 0:
|
|||
|
thread = threading.Thread(target=self.publish_topic,
|
|||
|
args=("calc_task", self.uncalc_ops, self.calc_port),
|
|||
|
name="calc_task")
|
|||
|
thread.start()
|
|||
|
time.sleep(15)
|
|||
|
|
|||
|
def publish_add_task(self, proof):
|
|||
|
|
|||
|
pub_data = {
|
|||
|
"data": list(self.uncalc_ops),
|
|||
|
"proof": proof,
|
|||
|
"index": len(self.chain.chain) + 1
|
|||
|
}
|
|||
|
print("即将发布新块:%s" % pub_data)
|
|||
|
self.ops_list.clear()
|
|||
|
self.chain.new_block(pub_data["data"], pub_data["proof"])
|
|||
|
thread = threading.Thread(target=self.publish_topic, args=("add_task", pub_data, self.add_port),
|
|||
|
name="add_task")
|
|||
|
thread.start()
|
|||
|
|
|||
|
def check_proofs(self, proof):
|
|||
|
|
|||
|
with lock:
|
|||
|
self.proof_list.append(proof)
|
|||
|
temp = list(self.proof_list)
|
|||
|
print("收到的证明列表:%s" % temp)
|
|||
|
if len(temp) == self.client_num:
|
|||
|
max_proof = max(temp, key=temp.count)
|
|||
|
print("占大多数的证明:%s" % max_proof)
|
|||
|
self.publish_add_task(proof)
|
|||
|
self.proof_list.clear()
|
|||
|
|
|||
|
def publish_topic(self, topic, topic_data, port):
|
|||
|
context = zmq.Context()
|
|||
|
publisher = context.socket(zmq.PUB)
|
|||
|
try:
|
|||
|
publisher.bind("tcp://{}:{}".format(self.server, port))
|
|||
|
print("publish_topic:bind:[%s]:%s" % (self.server, port))
|
|||
|
except zmq.ZMQError as e:
|
|||
|
print("publish_topic:bindfailed:[%s]:%s" % (e, port))
|
|||
|
|
|||
|
data_string = json.dumps(topic_data, sort_keys=True)
|
|||
|
print("publish_topic:send:[%s]:%s" % (topic, data_string))
|
|||
|
i = 0
|
|||
|
while True:
|
|||
|
publisher.send_multipart([bytes(topic, "utf-8"), bytes(data_string, 'utf-8')])
|
|||
|
time.sleep(2)
|
|||
|
i += 1
|
|||
|
if i == 2:
|
|||
|
print("publish_topic:finished")
|
|||
|
break
|
|||
|
|
|||
|
publisher.close()
|
|||
|
context.term()
|
|||
|
|
|||
|
def listen_msg(self):
|
|||
|
context = zmq.Context()
|
|||
|
socket = context.socket(zmq.REP)
|
|||
|
socket.bind("tcp://{}:{}".format(self.server, self.signal_port))
|
|||
|
|
|||
|
while True:
|
|||
|
message = socket.recv()
|
|||
|
message_dict = json.loads(message)
|
|||
|
print("Received: %s" % json.dumps(message_dict))
|
|||
|
|
|||
|
if message_dict["cmd"] == "new_proof":
|
|||
|
self.check_proofs(message_dict["msg"])
|
|||
|
response_string = json.dumps(build_msg("accept_proof", ""))
|
|||
|
socket.send(bytes(response_string, encoding="utf-8"))
|
|||
|
elif message_dict["cmd"] == "need_chain":
|
|||
|
data_dict = build_msg("new_chain", self.chain.full_chain())
|
|||
|
data_string = json.dumps(data_dict)
|
|||
|
socket.send(bytes(data_string, encoding="utf-8"))
|
|||
|
elif message_dict["cmd"] == "new_ops":
|
|||
|
self.add_ops(message_dict["msg"])
|
|||
|
response_string = json.dumps(build_msg("accept_ops", ""))
|
|||
|
socket.send(bytes(response_string, encoding="utf-8"))
|
|||
|
|
|||
|
|
|||
|
def add_fake_data(self):
|
|||
|
while True:
|
|||
|
data = (
|
|||
|
{
|
|||
|
"id": random.randint(0, 9),
|
|||
|
"operator": "operator",
|
|||
|
"option": "option",
|
|||
|
"commodity": "commodity",
|
|||
|
"time": get_current_time()
|
|||
|
}
|
|||
|
)
|
|||
|
self.add_ops(data)
|
|||
|
time.sleep(9)
|
|||
|
|
|||
|
|
|||
|
def get_current_time(frm="%Y-%m-%d %H:%M:%S"):
|
|||
|
dt = datetime.datetime.now()
|
|||
|
return dt.strftime(frm)
|
|||
|
|
|||
|
|
|||
|
if __name__ == '__main__':
|
|||
|
server = ZmqServer()
|
|||
|
|
|||
|
# add_fake_thread = threading.Thread(target=server.add_fake_data, name="客户端消息监听")
|
|||
|
# add_fake_thread.start()
|
|||
|
|
|||
|
publish_calc_task_thread = threading.Thread(target=server.publish_calc_task, name="客户端消息监听")
|
|||
|
publish_calc_task_thread.start()
|
|||
|
listen_thread = threading.Thread(target=server.listen_msg, name="客户端消息监听")
|
|||
|
listen_thread.start()
|