Java对等网络

时间:2018-06-28 05:11:16

标签: java networking peer

我正在尝试实现类似于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位哈希。

0 个答案:

没有答案