protected void send(Message message, boolean waitForConnected) { checkRunning(); if (waitForConnected) { // Make sure we aren't still connecting waitForConnected(); } ByteBuffer buffer = dataBuffer.get(); if (buffer == null) { buffer = ByteBuffer.allocate(65536 + 2); dataBuffer.set(buffer); } buffer.clear(); // Convert the message to bytes buffer = MessageProtocol.messageToBuffer(message, buffer); // Since we share the buffer between invocations, we will need to // copy this message's part out of it. This is because we actually // do the send on a background thread. byte[] temp = new byte[buffer.remaining()]; System.arraycopy(buffer.array(), buffer.position(), temp, 0, buffer.remaining()); buffer = ByteBuffer.wrap(temp); if (message.isReliable() || fast == null) { if (reliable == null) throw new RuntimeException("No reliable connector configured"); reliableAdapter.write(buffer); } else { fastAdapter.write(buffer); } }
public void start() { if (isRunning) throw new IllegalStateException("Client is already started."); // Start up the threads and stuff if (reliableAdapter != null) { reliableAdapter.start(); } if (fastAdapter != null) { fastAdapter.start(); } // Send our connection message with a generated ID until // we get one back from the server. We'll hash time in // millis and time in nanos. // This is used to match the TCP and UDP endpoints up on the // other end since they may take different routes to get there. // Behind NAT, many game clients may be coming over the same // IP address from the server's perspective and they may have // their UDP ports mapped all over the place. // // Since currentTimeMillis() is absolute time and nano time // is roughtly related to system start time, adding these two // together should be plenty unique for our purposes. It wouldn't // hurt to reconcile with IP on the server side, though. long tempId = System.currentTimeMillis() + System.nanoTime(); // Set it true here so we can send some messages. isRunning = true; ClientRegistrationMessage reg; if (reliable != null) { reg = new ClientRegistrationMessage(); reg.setId(tempId); reg.setGameName(getGameName()); reg.setVersion(getVersion()); reg.setReliable(true); send(reg, false); } if (fast != null) { // We create two different ones to prepare for someday // when there will probably be threaded sending. reg = new ClientRegistrationMessage(); reg.setId(tempId); reg.setReliable(false); send(reg, false); } }
public void close() { checkRunning(); // Send a close message // Tell the thread it's ok to die if (fastAdapter != null) { fastAdapter.close(); } if (reliableAdapter != null) { reliableAdapter.close(); } // Wait for the threads? // Just in case we never fully connected connecting.countDown(); fireDisconnected(null); isRunning = false; }