Package net.yura.lobby.client

Source Code of net.yura.lobby.client.SocketClient

package net.yura.lobby.client;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* @author Michael Chaten
*/
public abstract class SocketClient extends Thread {

    public static final Logger logger = Logger.getLogger( LobbyCom.class.getName() );

    private static final int HEADER_SIZE = 4; // a int to be sent as the size

    private ByteBuffer headerBuffer;
    private SocketChannel socketChannel;
    private volatile Selector poll;
    private boolean connected;

    private String server;
    private int port;

    private InetAddress ipAddr;

    public SocketClient() {
        super(null,null,"LobbyCom -- Main Thread",100000000);
        headerBuffer = ByteBuffer.allocateDirect(HEADER_SIZE);
    }

    public void connect(String sev, int p) {
        server = sev;
  port = p;
  start();
    }

    public void disconnect() {
        if (connected) {
            try {
                socketChannel.close();

                // TODO, this is not even close to enough
            }
            catch (IOException e) { }
        }
    }

    public void run() {

  try {
    ipAddr = InetAddress.getByName(server);
  }
  catch(Exception ex) {
    // cant work out who to connect to, this is very bad!
    throw new RuntimeException(ex);
  }

  // This will ALWAYS LOOP
  while (true) {

    try {
      // make a connection
      log("Trying to connect to: "+ipAddr+":"+port);

      poll = Selector.open();
      socketChannel = SocketChannel.open();
      socketChannel.configureBlocking(false);
      socketChannel.connect(new InetSocketAddress(ipAddr, port));
      socketChannel.register(poll,SelectionKey.OP_CONNECT);
      log("Pending Connection");

      SocketChannel sock;
      Iterator iterator;

      // go into the loop of when we are connected
      while (true) {

        if (poll.select() != 0) {

          iterator = poll.selectedKeys().iterator();

          while (iterator.hasNext()) {

            SelectionKey key = (SelectionKey) iterator.next();

            if (key.isConnectable()) {

              // finish doing the connection

              sock = (SocketChannel) key.channel();
                                                        boolean result = sock.finishConnect();
              log("Finished Connecting "+result);
              poll = Selector.open();
              sock.register(poll, SelectionKey.OP_READ);
              connected = true;
              log("Initializing Handshake");
                                                       
                                                        connected();
            }

            if (key.isReadable()) {

              // we are connected, lets read data!

              sock = (SocketChannel)key.channel();

              try {
                analyzeMessage(sock);
              }
              catch (IOException e) {

                key.cancel();
                throw e;

              }

            }

            iterator.remove();
          }
        }
      }
    }
    catch (IOException e) {

      // if there is some IO Error we will log it, then try to reconnect
                        // currently this includes errors like the server not being available
                        logger.log(Level.INFO, "lobby com error", e);

      connected = false;
      disconnected();
      // now will try and reconnect again

      // sleep for a bit, not to hurt the server
      try { Thread.sleep(1000); } catch(Exception ex) {}
    }
  }

    }

    public void sendToNetwork(byte[] bytes) {

        try {

            ByteBuffer[] writeBuffers = new ByteBuffer[]{ByteBuffer.allocate(HEADER_SIZE), null};
            writeBuffers[0].putInt(bytes.length);
            writeBuffers[0].flip();

            writeBuffers[1] = ByteBuffer.wrap(bytes);

            long bytesWritten = 0;
            long bytesToWrite = writeBuffers[0].limit() + writeBuffers[1].limit();
            while (bytesWritten < bytesToWrite) {
                    bytesWritten += socketChannel.write(writeBuffers);
            }
     
        }
        catch (IOException e) {
            e.printStackTrace();
        }
     
    }

    private void analyzeMessage(SocketChannel sc) throws IOException {
        sc.read(headerBuffer);
        if (headerBuffer.position() == 0) {
            throw new IOException("Read 0 bytes");
        }
        headerBuffer.flip();
        final int messageLen = headerBuffer.getInt();
        headerBuffer.clear();
        ByteBuffer messageBuffer = ByteBuffer.allocate(messageLen);
        int read = 0;

        while (read != messageLen) {

            read += sc.read(messageBuffer);
        }

        messageBuffer.flip();

        gotMessage( messageBuffer.array() );
    }

    abstract void log(String msg);
    abstract void connected();
    abstract void disconnected();
    abstract void gotMessage(byte[] bytes);

}
TOP

Related Classes of net.yura.lobby.client.SocketClient

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.