我正在尝试实现类似于Kademlia的p2p网络系统,但我使用的是TCP而不是UDP。因此,在连接“最终确定”之前,我需要在两个对等连接之间执行地址交换。
当前,我正在尝试通过在最终确定连接之前将连接最初接受为PotentialPeer来实现此目的。但是,PotentialPeer从未解决为标准Peer,我希望有人可以帮助我找出原因。
这是接受连接并处理(在工作时)PotentialPeer对等解析的主要实例
public class Peer2Peer extends Thread {
private int port;
private boolean running;
private boolean initialized;
private ServerSocket server;
private PeerSet peers;
protected static ECKey key;
protected static HashMap<Integer, NetworkCommand> commands = new HashMap<>();
public static ArrayList<PotentialPeer> waitList = new ArrayList<>();
public Peer2Peer(int port, ECKey key, int k) {
try {
this.port = port;
this.peers = new PeerSet(key.getAddress(), k);
this.key = key;
initializeCommands();
server = new ServerSocket(this.port);
this.initialized = true;
} catch (Exception e) {
this.initialized = false;
}
}
public void connect(String s, int port) {
try {
Socket sock = new Socket();
System.out.println("Socket created");
sock.connect(new InetSocketAddress(s, port), 3000);
System.out.println("Socket connected");
PotentialPeer p = new PotentialPeer(sock);
System.out.println("PotentialPeer initialized");
p.start();
System.out.println("PotentialPeer Started");
this.waitList.add(p);
System.out.println("PotentialPeer Added to Waitlist");
p.send(1, key.getAddress());
System.out.println("Connection Message Sent");
} catch (Exception e) {
System.out.println("Connection failed.");
}
}
private void initializeCommands() {
commands.put(1, new TextCommand());
}
public void broadcast(int n, byte[] in) {
peers.broadcast(n, in);
}
@Override
public void run() {
running = true;
while (running) {
try {
Socket s = server.accept();
if (s != null) {
PotentialPeer p = new PotentialPeer(s);
p.start();
waitList.add(p);
p.send(1, key.getAddress());
for (int i = 0; i < waitList.size(); i++) {
if (waitList.get(i).toDelete()) {
waitList.remove(i).stop();
} else if (waitList.get(i).hasAddress()) {
PotentialPeer pot = waitList.remove(i);
Peer newPeer = new Peer(pot.getAddress(), pot.getSocket());
newPeer.start();
peers.add(newPeer);
}
}
}
} catch (Exception e) {
throw new RuntimeException("The server has failed.", e);
}
}
}
public String getPeers() {
return peers.toString();
}
}
与此相伴的是对等代码:
public class Peer extends Thread {
private byte[] address;
private Socket socket;
private DataOutputStream out;
private DataInputStream in;
private boolean running;
private boolean initialized;
public Peer(byte[] address, Socket socket) {
try {
this.address = address;
this.socket = socket;
this.out = new DataOutputStream(socket.getOutputStream());
this.in = new DataInputStream(socket.getInputStream());
this.initialized = true;
} catch (Exception e) {
this.initialized = false;
}
}
public byte[] getAddress() {
return address;
}
public boolean isRunning() {
return running;
}
@Override
public void run() {
running = true;
while (running) {
uMessage received = receive(in);
if (received != null) {
send(serveType(received), serve(received));
}
}
}
public byte[] serve(uMessage in) {
if (commands.containsKey(in.getMessageType())) {
return commands.get(in.getMessageType()).handle(in);
} else {
return null;
}
}
public int serveType(uMessage in) {
return 1;
/* TODO: Replace with actual message type handling */
}
public uMessage receive(DataInputStream in) {
try {
byte[] chunk;
ArrayList<byte[]> blob = new ArrayList<>();
int count;
do {
chunk = new byte[32];
count = in.read(chunk);
if (count != 32) {
return null;
}
blob.add(chunk);
} while (chunk[0] == 0);
System.out.println("Received: " + Hex.toHexString(deblobify(blob)));
return new uMessage(deblobify(blob));
} catch (Exception e) {
return null;
}
}
public void send(int i, byte[] data) {
try {
if (data != null) {
uMessage u = new uMessage(i, data, Peer2Peer.key.getPrivKeyBytes());
byte[] message = u.getEncoded();
System.out.println("Sending: " + Hex.toHexString(message));
byte[] toSend = semiblobify(message);
out.write(toSend.length);
out.write(toSend);
out.flush();
}
} catch (Exception e) {
this.running = false;
}
}
public String toString() {
String s = "";
s = s + Hex.toHexString(address) + ": ";
s = s + socket.getInetAddress().toString() + ":" + socket.getPort() + "\n";
return s;
}
}
和潜在对等类:
public class PotentialPeer extends Peer {
Socket s;
long initialized;
byte[] address;
protected PotentialPeer(Socket s) {
super(null, s);
this.s = s;
this.initialized = System.currentTimeMillis();
}
public boolean hasAddress() {
return (address != null);
}
public byte[] getAddress() {
return address;
}
public Socket getSocket() {
return s;
}
public boolean toDelete() {
if ((System.currentTimeMillis() - this.initialized) > 1000) {
if (!hasAddress()) {
return true;
} else {
return false;
}
} else {
return false;
}
}
@Override
public byte[] serve(uMessage in) {
byte[] temp = in.getPayload();
if (temp.length != 32) {
return null;
} else {
this.address = temp;
return Peer2Peer.key.getAddress();
}
}
@Override
public void run() {
try {
boolean running = true;
while (running) {
uMessage received = super.receive(new DataInputStream(s.getInputStream()));
if (received != null) {
send(0, serve(received));
}
}
} catch (Exception e) {
}
}
}
如果有帮助,请参见完整代码: https://github.com/Levalicious/NetTests
我知道信息已经转移,因为我在两面都看到确认,但是由于某种原因,它不处理接收的地址并添加它。如果一切正常,PotentialPeers会很快解决,但他们只是坐在那里而没有任何活动。
编辑:通过地址澄清,我的意思是我用于协议的异或度量而不是IP地址的EC公钥的256位哈希。