我使用Kademlia库来创建 P2P 网络。一旦节点加入网络,我希望用户能够在命令行中请求获取密钥或将元组放入网络。
我的问题是 I/O 阻塞了连接,这意味着在用户输入时节点将与网络断开连接。
我的代码如下:
from kademlia.network import Server
from twisted.internet import reactor, stdio
from twisted.python import log
from twisted.internet.task import LoopingCall
import sys
log.startLogging(sys.stdout)
def usi(server):
key = str(raw_input())
value = str(raw_input())
print("Putting data: (" + key + ";" + value + ")")
server.set(key, value).addCallback(done)
def done(res):
print "Key put:"
print res
def boostrapDone(found, server, key):
if len(found) == 0:
print 'could not bootstrap'
reactor.stop()
server.set(key, 'value').addCallback(done)
srv = Server()
srv.saveStateRegularly('out.pik')
srv.listen(8887)
srv.bootstrap([('127.0.0.1', 8888)]).addCallback(boostrapDone, srv, 'test')
loop = LoopingCall(usi, srv)
loop.start(2)
reactor.run()
我已经阅读了几个关于这个问题的 SO 问题,并且我已经阅读了 twisted 示例中的 stdin.py 和 stdio.py 示例,似乎我需要在 twisted 协议上使用 StandardIO。但是 Kademlia 使用了一个高级类(Server)来简化协议的使用,不知道是否可以在不修改库的情况下获得非阻塞 I/O。
编辑:我尝试使用reactor.callInThread
这种方式:
def usi(server):
while True:
key = str(raw_input())
value = str(raw_input())
print("Putting data: (" + key + ";" + value + ")")
server.set(key, value).addCallback(done)
def done(res):
print "Key put:"
print res
def boostrapDone(found, server, key):
if len(found) == 0:
print 'could not bootstrap'
reactor.stop()
server.set(key, 'value').addCallback(done)
srv = Server()
srv.saveStateRegularly('out.pik')
srv.listen(8887)
srv.bootstrap([('127.0.0.1', 8888)]).addCallback(boostrapDone, srv, 'test')
reactor.callInThread(usi, srv)
reactor.run()
它似乎有效,但有时节点无法从其他节点获得响应,并将它们从他的存储桶中删除,使他无法将元组放入网络,所以我想我仍然做错了什么。(我设法重现了这个错误,它似乎发生在用户输入超过 5 秒时,kademlia 无法接收来自其他节点的响应并将它们超时)