基于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; } } } }