Android Open Source - android_asyncsocket Tcp Client






From Project

Back to project page android_asyncsocket.

License

The source code is released under:

GNU Lesser General Public License

If you think the Android project android_asyncsocket listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.smorra.asyncsocket;
/*from w w w  . j av a  2s  .c o m*/
import java.io.IOException;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.Pipe;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;

import android.app.Activity;
import android.os.Handler;
import android.os.Looper;

public class TcpClient extends Thread implements DnsResolverCallback
{
  TcpClientCallback tcc;
  DnsResolver dr;
  String host;
  int port;
  InetAddress ia;
  Pipe p;
  BigInteger bytesWritten = BigInteger.ZERO;
  BigInteger bytesQueued = BigInteger.ZERO;

  enum State
  {
    RESOLVING, CLOSED, CONNECTING, CONNECTED
  }

  State state = State.RESOLVING;

  public int bytesInQueue()
  {
    return bytesQueued.subtract(bytesWritten).intValue();
  }

  public TcpClient(TcpClientCallback tcc, String host, int port) throws IOException
  {
    this.tcc = tcc;
    this.host = host;
    this.port = port;
    p = Pipe.open();
    p.sink().configureBlocking(true);
    p.source().configureBlocking(false);
    dr = new DnsResolver(this, host);
  }

  public void write(byte[] b) throws IOException, InterruptedException
  {
    if (state != State.CONNECTED)
      throw new IOException("not connected");
    p.sink().write(ByteBuffer.wrap(new byte[] { 0 }));
    ByteBuffer bb = ByteBuffer.allocate(4);
    bb.putInt(b.length);
    bb.rewind();
    p.sink().write(bb);

    p.sink().write(ByteBuffer.wrap(b));
    bytesQueued = bytesQueued.add(BigInteger.valueOf(b.length));
  }

  public void close() throws IOException
  {
    if (state == State.CLOSED)
      throw new IOException("already closed");

    if (state == State.RESOLVING)
      dr.cancel();

    state = State.CLOSED;
    p.sink().write(ByteBuffer.wrap(new byte[] { 1 }));

  }

  @Override
  public void run()
  {
    try
    {
      SocketChannel sc = SocketChannel.open();
      boolean connected = false;
      byte[] writeBuffer = new byte[0];
      byte[] readBuffer = new byte[0];
      sc.configureBlocking(false);
      sc.connect(new InetSocketAddress(ia, port));
      while (true)
      {

        Selector selector = Selector.open();
        if (!connected)
        {
          sc.register(selector, SelectionKey.OP_CONNECT);
        }
        else
        {
          sc.register(selector, SelectionKey.OP_READ);
          if (writeBuffer.length != 0)
            sc.register(selector, SelectionKey.OP_WRITE);
        }
        p.source().register(selector, SelectionKey.OP_READ);

        selector.select();

        for (SelectionKey k : selector.selectedKeys())
        {
          if (k.channel() == sc && k.isConnectable())
          {
            try
            {
              if (sc.finishConnect())
              {
                connected = true;
                new Handler(Looper.getMainLooper()).post(new Runnable()
                {
                  @Override
                  public void run()
                  {
                    if (state == State.CLOSED)
                      return;
                    state = State.CONNECTED;
                    tcc.onConnect(TcpClient.this);
                  }
                });
              }
            }
            catch (Exception e)
            {
              System.out.println("MOH");
              e.printStackTrace();
              sc.close();
              new Handler(Looper.getMainLooper()).post(new Runnable()
              {
                @Override
                public void run()
                {
                  state = State.CLOSED;
                  tcc.onConnectFailed(TcpClient.this);
                }
              });
              return;
            }
          }
          else if (k.channel() == sc && k.isReadable())
          {
            ByteBuffer b = ByteBuffer.allocate(1024);

            int n = -1;
            try
            {
              n = sc.read(b);
            }
            catch (Exception e)
            {
            }
            if (n == -1)
            {
              sc.close();
              new Handler(Looper.getMainLooper()).post(new Runnable()
              {

                @Override
                public void run()
                {
                  if (state == State.CLOSED)
                    return;

                  tcc.onDisconnected(TcpClient.this);

                }
              });
              return;
            }
            byte[] bytes = new byte[n];
            System.arraycopy(b.array(), 0, bytes, 0, n);
            final byte[] readBytes = bytes;
            new Handler(Looper.getMainLooper()).post(new Runnable()
            {

              @Override
              public void run()
              {
                if (state == State.CLOSED)
                  return;
                tcc.onRead(TcpClient.this, readBytes);

              }
            });
          }
          else if (k.channel() == sc && k.isWritable())
          {
            //System.out.println("IS WRITABLE");
            final int n;
            try
            {
              n = sc.write(ByteBuffer.wrap(writeBuffer));
            }
            catch (Exception e)
            {
              sc.close();
              new Handler(Looper.getMainLooper()).post(new Runnable()
              {

                @Override
                public void run()
                {
                  if (state == State.CLOSED)
                    return;

                  tcc.onDisconnected(TcpClient.this);

                }
              });
              return;
            }
            byte[] newWriteBuffer = new byte[writeBuffer.length - n];
            System.arraycopy(writeBuffer, n, newWriteBuffer, 0, writeBuffer.length - n);
            writeBuffer = newWriteBuffer;
            if (writeBuffer.length == 0)
            {
              new Handler(Looper.getMainLooper()).post(new Runnable()
              {

                @Override
                public void run()
                {
                  bytesWritten = bytesWritten.add(BigInteger.valueOf(n));
                  if (state == State.CONNECTED && bytesWritten.equals(bytesQueued))
                  {
                    tcc.onWritten(TcpClient.this);
                  }
                }
              });

            }

          }
          else if (k.channel() == p.source() && k.isReadable())
          {
            while (true)
            {
              ByteBuffer bb = ByteBuffer.allocate(1024);
              int n = p.source().read(bb);
              //System.out.println("Bytes read: " + n);
              byte[] readBuffer2 = new byte[readBuffer.length + n];
              System.arraycopy(readBuffer, 0, readBuffer2, 0, readBuffer.length);
              System.arraycopy(bb.array(), 0, readBuffer2, readBuffer.length, n);
              readBuffer = readBuffer2;

              if (n != bb.capacity())
                break;
            }

            while (true)
            {
              if (readBuffer.length >= 5 && readBuffer[0] == 0)
              { // write command
                byte[] length = new byte[] { readBuffer[1], readBuffer[2], readBuffer[3], readBuffer[4] };
                int ilength = ByteBuffer.wrap(length).getInt();

                if (readBuffer.length >= 5 + ilength)
                {
                  byte[] wdata = new byte[ilength];
                  System.arraycopy(readBuffer, 5, wdata, 0, ilength);

                  byte[] writeBufferNew = new byte[writeBuffer.length + wdata.length];
                  System.arraycopy(writeBuffer, 0, writeBufferNew, 0, writeBuffer.length);
                  System.arraycopy(wdata, 0, writeBufferNew, writeBuffer.length, ilength);
                  writeBuffer = writeBufferNew;

                  byte[] readBufferNew = new byte[readBuffer.length - 5 - ilength];
                  System.arraycopy(readBuffer, 5 + ilength, readBufferNew, 0, readBuffer.length - 5 - ilength);
                  readBuffer = readBufferNew;
                }
                else
                {
                  break;
                }
              }
              else if (readBuffer.length >= 1 && readBuffer[0] == 1)
              { // close
                sc.close();
                return;
              }
              else
              { // no more commands
                break;
              }
            }

          }
        }
        selector.close();
      }
    }
    catch (IOException e)
    {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

  @Override
  public void onResolved(InetAddress[] ia)
  {
    this.ia = ia[0];
    this.state = State.CONNECTING;
    start();
  }

  @Override
  public void onResolveFailed()
  {
    state = State.CLOSED;
    System.out.println("DNS FAILED");
    tcc.onConnectFailed(this);
  }

}




Java Source Code List

com.smorra.asyncsocket.DnsResolverCallback.java
com.smorra.asyncsocket.DnsResolver.java
com.smorra.asyncsocket.SSLClientCallback.java
com.smorra.asyncsocket.SSLClient.java
com.smorra.asyncsocket.TcpClientCallback.java
com.smorra.asyncsocket.TcpClient.java
com.smorra.asyncsocket.TcpServerCallback.java
com.smorra.asyncsocket.TcpServerClientCallback.java
com.smorra.asyncsocket.TcpServerClient.java
com.smorra.asyncsocket.TcpServer.java