public Connection(String host, int port) { server_port = port; server_addr = host; packets = new LinkedList<Packet>(); recv_worker = new RecvWorker(); recv_worker.start(); }
/** * If this server has initiated the connection, then it gives up on the connection if it loses * challenge. Otherwise, it keeps the connection. */ public boolean initiateConnection(Socket sock, Long sid) { DataOutputStream dout = null; try { // Sending id and challenge dout = new DataOutputStream(sock.getOutputStream()); dout.writeLong(self.getId()); dout.flush(); } catch (IOException e) { LOG.warn("Ignoring exception reading or writing challenge: ", e); closeSocket(sock); return false; } // If lost the challenge, then drop the new connection if (sid > self.getId()) { LOG.info( "Have smaller server identifier, so dropping the " + "connection: (" + sid + ", " + self.getId() + ")"); closeSocket(sock); // Otherwise proceed with the connection } else { SendWorker sw = new SendWorker(sock, sid); RecvWorker rw = new RecvWorker(sock, sid, sw); sw.setRecv(rw); SendWorker vsw = senderWorkerMap.get(sid); if (vsw != null) vsw.finish(); senderWorkerMap.put(sid, sw); if (!queueSendMap.containsKey(sid)) { queueSendMap.put(sid, new ArrayBlockingQueue<ByteBuffer>(SEND_CAPACITY)); } sw.start(); rw.start(); return true; } return false; }
/** * If this server receives a connection request, then it gives up on the new connection if it * wins. Notice that it checks whether it has a connection to this server already or not. If it * does, then it sends the smallest possible long value to lose the challenge. */ public boolean receiveConnection(Socket sock) { Long sid = null; try { // Read server id DataInputStream din = new DataInputStream(sock.getInputStream()); sid = din.readLong(); if (sid == QuorumPeer.OBSERVER_ID) { /* * Choose identifier at random. We need a value to identify * the connection. */ sid = observerCounter--; LOG.info("Setting arbitrary identifier to observer: " + sid); } } catch (IOException e) { closeSocket(sock); LOG.warn("Exception reading or writing challenge: " + e.toString()); return false; } // If wins the challenge, then close the new connection. if (sid < self.getId()) { /* * This replica might still believe that the connection to sid is * up, so we have to shut down the workers before trying to open a * new connection. */ SendWorker sw = senderWorkerMap.get(sid); if (sw != null) { sw.finish(); } /* * Now we start a new connection */ LOG.debug("Create new connection to server: " + sid); closeSocket(sock); connectOne(sid); // Otherwise start worker threads to receive data. } else { SendWorker sw = new SendWorker(sock, sid); RecvWorker rw = new RecvWorker(sock, sid, sw); sw.setRecv(rw); SendWorker vsw = senderWorkerMap.get(sid); if (vsw != null) vsw.finish(); senderWorkerMap.put(sid, sw); if (!queueSendMap.containsKey(sid)) { queueSendMap.put(sid, new ArrayBlockingQueue<ByteBuffer>(SEND_CAPACITY)); } sw.start(); rw.start(); return true; } return false; }
/* * 读取对方的sid */ public boolean receiveConnection(Socket sock) { Long sid = null; try { // Read server id DataInputStream din = new DataInputStream(sock.getInputStream()); sid = din.readLong(); if (sid < 0) { // this is not a server id but a protocol version // (see ZOOKEEPER-1633) sid = din.readLong(); // next comes the #bytes in the remainder of the message int num_remaining_bytes = din.readInt(); byte[] b = new byte[num_remaining_bytes]; // remove the remainder of the message from din int num_read = din.read(b); if (num_read != num_remaining_bytes) { LOG.error( "Read only " + num_read + " bytes out of " + num_remaining_bytes + " sent by server " + sid); } } if (sid == QuorumPeer.OBSERVER_ID) { /* * Choose identifier at random. We need a value to identify the * connection. */ sid = observerCounter--; LOG.info("Setting arbitrary identifier to observer: " + sid); } } catch (IOException e) { closeSocket(sock); LOG.warn("Exception reading or writing challenge: " + e.toString()); return false; } // If wins the challenge, then close the new connection. /* * 只允许sid大的连接小的 */ if (sid < self.getId()) { /* * This replica might still believe that the connection to sid is * up, so we have to shut down the workers be fore trying to open a * new connection. */ SendWorker sw = senderWorkerMap.get(sid); if (sw != null) { sw.finish(); } /* * Now we start a new connection */ LOG.debug("Create new connection to server: " + sid); closeSocket(sock); connectOne(sid); // Otherwise start worker threads to receive data. } else { SendWorker sw = new SendWorker(sock, sid); RecvWorker rw = new RecvWorker(sock, sid, sw); sw.setRecv(rw); SendWorker vsw = senderWorkerMap.get(sid); if (vsw != null) vsw.finish(); senderWorkerMap.put(sid, sw); if (!queueSendMap.containsKey(sid)) { queueSendMap.put(sid, new ArrayBlockingQueue<ByteBuffer>(SEND_CAPACITY)); } sw.start(); rw.start(); return true; } return false; }