基于TCP Socket的Android通信组件

这个组件是很早之前写的了,当时的一个需求是需要实现在Android手机客户端的长连接,所以需要用到socket通信,当时查阅了相关资料,在其他前辈的基础上,整理出这样一个组件,其中肯定还有许多问题,但还是先放出来吧。

实现的原理很简单,开启一个子线程,与服务器通信,并且实现了断线重连,获取到数据以后回调接口,不阻塞主线程。

连接服务器线程类

package org.yong.tcpsocket;

import java.util.Vector;

import android.util.Log;

/**
 * 连接服务器线程类
 * 
 * @author Cheng Yong
 */
public class TCPSocketConnect implements Runnable {

    private boolean isConnect = false;// 是否连接服务器
    private boolean isWrite = false;// 是否发送数据
    private static Vector<byte[]> datas = new Vector<byte[]>();// 待发送数据队列
    private Object lock = new Object();// 连接锁对象
    private TCPSocketFactory mSocket;// socket连接
    private WriteRunnable writeRunnable;// 发送数据线程
    private String ip = null;
    private int port = -1;

    /**
     * 创建连接
     * 
     * @param callback
     *            回调接口
     * @param executor
     *            线程池对象
     */
    public TCPSocketConnect(TCPSocketCallback callback) {
        mSocket = new TCPSocketFactory(callback);// 创建socket连接
        writeRunnable = new WriteRunnable();// 创建发送线程
    }

    @Override
    public void run() {
        if (ip == null || port == -1) {
            return;
        }
        isConnect = true;
        while (isConnect) {
            synchronized (lock) {
                try {
                    Log.e("TCPSocketConnect",">TCP连接服务器<");
                    mSocket.connect(ip, port);// 连接服务器
                } catch (Exception e) {
                    try {
                        Log.e("TCPSocketConnect",">TCP连接服务器失败, 6秒后重新连接<");
                        resetConnect();// 断开连接
                        lock.wait(6000);
                        continue;
                    } catch (InterruptedException e1) {
                        continue;
                    }
                }
            }
            Log.e("TCPSocketConnect",">TCP连接服务器成功<");
            isWrite = true;// 设置可发送数据
            new Thread(writeRunnable).start();// 在线程池启动发送线程
            try {
                mSocket.read();// 获取数据
            } catch (Exception e) {
                Log.e("TCPSocketConnect",">TCP连接异常<", e);
            } finally {
                Log.e("TCPSocketConnect",">TCP连接中断<");
                resetConnect();// 断开连接
            }
        }
        Log.e("TCPSocketConnect",">=TCP结束连接线程=<");
    }

    /**
     * 关闭服务器连接
     */
    public void disconnect() {
        synchronized (lock) {
            isConnect = false;
            lock.notify();
            resetConnect();
        }
    }

    /**
     * 重置连接
     */
    public void resetConnect() {
        Log.e("TCPSocketConnect",">TCP重置连接<");
        writeRunnable.stop();// 发送停止信息
        mSocket.disconnect();
    }

    /**
     * 向发送线程写入发送数据
     */
    public void write(byte[] buffer) {
        writeRunnable.write(buffer);
    }

    /**
     * 设置IP和端口
     * 
     * @param ip
     * @param port
     */
    public void setAddress(String host, int port) {
        this.ip = host;
        this.port = port;
    }

    /**
     * 发送数据
     */
    private boolean writes(byte[] buffer) {
        try {
            mSocket.write(buffer);
            Thread.sleep(1);
            return true;
        } catch (Exception e) {
            resetConnect();
            return false;
        }
    }

    /**
     * 发送线程
     * 
     * @author Esa
     */
    private class WriteRunnable implements Runnable {

        private Object wlock = new Object();// 发送线程锁对象

        @Override
        public void run() {
            Log.e("TCPSocketConnect",">TCP发送线程开启<");
            while (isWrite) {
                synchronized (wlock) {
                    if (datas.size() <= 0) {
                        try {
                            wlock.wait();// 等待发送数据
                        } catch (InterruptedException e) {
                            continue;
                        }
                    }
                    while (datas.size() > 0) {
                        byte[] buffer = datas.remove(0);// 获取一条发送数据
                        if (isWrite) {
                            writes(buffer);// 发送数据
                        } else {
                            wlock.notify();
                        }
                    }
                }
            }
            Log.e("TCPSocketConnect",">TCP发送线程结束<");
        }

        /**
         * 添加数据到发送队列
         * 
         * @param buffer
         *            数据字节
         */
        public void write(byte[] buffer) {
            synchronized (wlock) {
                datas.add(buffer);// 将发送数据添加到发送队列
                wlock.notify();// 取消等待
            }
        }

        public void stop() {
            synchronized (wlock) {
                isWrite = false;
                wlock.notify();
            }
        }
    }
}

 

获取网络数据回调类

package org.yong.tcpsocket;

/**
 * 获取网络数据回调类
 * 
 * @author Cheng Yong
 * 
 */
public abstract interface TCPSocketCallback {
    
    /**
     * 断开连接
     */
    public static final int TCP_DISCONNECTED = 0;
    
    /**
     * 已连接
     */
    public static final int TCP_CONNECTED = 1;
    
    /**
     * 连接获得数据
     */
    public static final int TCP_DATA = 2;

    /**
     * 当建立连接是的回调
     */
    public abstract void tcp_connected();

    /**
     * 当获取网络数据回调接口
     * 
     * @param buffer
     *            字节数据
     */
    public abstract void tcp_receive(byte[] buffer);

    /**
     * 当断开连接的回调
     */
    public abstract void tcp_disconnect();

}

 

Socket连接操作类

package org.yong.tcpsocket;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.UnknownHostException;

/**
 * Socket连接操作类
 * 
 * @author Cheng Yong
 */
public class TCPSocketFactory {

    private Socket mSocket;// socket连接对象
    private DataOutputStream out;
    private DataInputStream in;// 输入流
    private byte[] buffer = new byte[1024*1];// 缓冲区字节数组,信息不能大于此缓冲区
    private byte[] tmpBuffer;// 临时缓冲区
    private TCPSocketCallback callback;// 信息回调接口
    private int timeOut = 1000 * 30;

    /**
     * 构造方法传入信息回调接口对象
     * 
     * @param sdi
     *  回调接口
     */
    public TCPSocketFactory(TCPSocketCallback callback) {
        this.callback = callback;
    }

    /**
     * 连接网络服务器
     * 
     * @throws UnknownHostException
     * @throws IOException
     */
    public void connect(String ip, int port) throws Exception {
        mSocket = new Socket();
        SocketAddress address = new InetSocketAddress(ip, port);
        mSocket.connect(address, timeOut);// 连接指定IP和端口
        if (isConnected()) {
            out = new DataOutputStream(mSocket.getOutputStream());// 获取网络输出流
            in = new DataInputStream(mSocket.getInputStream());// 获取网络输入流
            if (isConnected()) {
                callback.tcp_connected();
            }
        }
    }

    public void setTimeOut(int timeOut) {
        this.timeOut = timeOut;
    }

    /**
     * 返回连接服是否成功
     * 
     * @return
     */
    public boolean isConnected() {
        if (mSocket == null || mSocket.isClosed()) {
            return false;
        }
        return mSocket.isConnected();
    }

    /**
     * 发送数据
     * 
     * @param buffer
     *            信息字节数据
     * @throws IOException
     */
    public void write(byte[] buffer) throws IOException {
        if (out != null) {
            out.write(buffer);
            out.flush();
        }
    }

    /**
     * 断开连接
     * 
     * @throws IOException
     */
    public void disconnect() {
        try {
            if (mSocket != null) {
                if (!mSocket.isInputShutdown()) {
                    mSocket.shutdownInput();
                }
                if (!mSocket.isOutputShutdown()) {
                    mSocket.shutdownOutput();
                }
            }
            if (out != null) {
                out.close();
            }
            if (in != null) {
                in.close();
            }
            if (mSocket != null && !mSocket.isClosed()) {// 判断socket不为空并且是连接状态
                mSocket.close();// 关闭socket
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            callback.tcp_disconnect();
            out = null;
            in = null;
            mSocket = null;// 制空socket对象
        }
    }

    /**
     * 读取网络数据
     * 
     * @throws IOException
     */
    public void read() throws IOException {
        if (in != null) {
            int len = 0;// 读取长度
            while ((len = in.read(buffer)) > 0) {
                tmpBuffer = new byte[len];// 创建临时缓冲区
                System.arraycopy(buffer, 0, tmpBuffer, 0, len);// 将数据拷贝到临时缓冲区
                callback.tcp_receive(tmpBuffer);// 调用回调接口传入得到的数据
                tmpBuffer = null;
            }
        }
    }
}

 

标签:none