最近工作上要用到的通信技术点-Socket, 在2012年的时候就学习过socket编程,那时主要使用Unix C实现的, 学完以后也没有使用过,现在做Android开发使用Java语言实现与那时Unix C实现基本一样。
1、创建Socket;
2、打开连接到Socket的输入/出流;
3、按照一定的协议对Socket进行读/写操作;
4、关闭Socket;

Socket是什么呢,百度百科概念

网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。

Socket的英文原义是“孔”或“插座”。作为BSD UNIX的进程通信机制,取后一种意思。通常也称作”套接字”,用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。在Internet上的主机一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。Socket正如其英文原意那样,像一个多孔插座。

直奔主题,Socket在安卓中的使用

很多时候做Android开发直接使用socket并不多,多数情况下使用Http通信还是使用别人封装好的库如 OkHttp, Volley, xUtil, Android-async-http等,然而应用层下的Http 协议也是基于Socket实现的。

同样,工作中我也是使用GitHub上的库,方便在于它为我们封装好几个重要的回调接口:

* Socket 连接
* Socket 收到数据
* Socket 关闭或被关闭

这个库AndroidAsync在GitHub有超过5000多人star,功能很强大, 支持有:

* Socket client + socket server
* HTTP client + server
* WebSocket client + server

是不是心动了,star下来,以后留着用吧,贴下我封装的代码

    /**
     * Created by sunfusheng on 15/10/17.
     */
    public class SocketClient implements Runnable {

        private String TAG = "log-" + this.getClass().getSimpleName();
        private AsyncSocket asyncSocket = null;
        private String host; //IP地址
        private int port; //端口
        private static SocketClient single = null;

        private final int ONE_SECOND = 1000;
        private final int TIME_CONNECT_FAILED_DELAY = 5;
        private final int TIME_CONNECT_SUCCESS_DELAY = 30;

        private int reConnectCount = 0;
        private boolean isConnected = false;

        private static final int CONNECT_SUCCESS = 0;
        private static final int CONNECT_FAILED = 1;

        Handler mHandler = new Handler() {

            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                switch (msg.what) {
                    case CONNECT_SUCCESS:
                        sendConnectInfo();
                        break;
                    case CONNECT_FAILED:
                        closeSocket();
                        connect();
                        break;
                }
            }
        };

        //Socket 重连机制
        @Override
        public void run() {
            mHandler.postDelayed(this, ONE_SECOND);
            reConnectCount ++;
            if (isConnected) {
                if (reConnectCount > TIME_CONNECT_SUCCESS_DELAY) {
                    reConnectCount = 0;
                    sendMessage(CONNECT_SUCCESS);
                }
            } else {
                if (reConnectCount%TIME_CONNECT_FAILED_DELAY == 0) {
                    sendMessage(CONNECT_FAILED);
                }
            }
        }

        private void sendMessage(int what) {
            Message msg = mHandler.obtainMessage();
            msg.what = what;
            mHandler.sendMessage(msg);
        }

        //发送连接成功确认信息
        private void sendConnectInfo() {
            SocketSimpleEntity entity = new SocketSimpleEntity();
            entity.inname = SocketResponseType.TYPE_CONNECT;
            entity.status = 200;
            entity.info = "onConnect OK ...";
            writeString(FastJsonUtil.createJson(entity));
        }

        //处理连接成功信息
        private void handleConnectSocket(String jsonStr) {
            try {
                JSONObject jsonObject = new JSONObject(jsonStr);
                String responseType = jsonObject.getString(SocketResponseType.TYPE_KEY);
                if (responseType.equals(SocketResponseType.TYPE_CONNECT)) {
                    reConnectCount = 0;
                    SocketSimpleEntity socketSimpleEntity = FastJsonUtil.parseJson(jsonStr, SocketSimpleEntity.class);
                    if (socketSimpleEntity.status == 200) {
                        isConnected = true;
                    } else {
                        isConnected = false;
                    }
                }
            } catch (JSONException e) {}
        }

        private SocketClient(String host, int port) {
            this.host = host;
            this.port = port;
            mHandler.postDelayed(this, ONE_SECOND);
        }

        public static SocketClient getInstance() {
            if (single == null) {
                single = new SocketClient(ConstantParams.IP, ConstantParams.PORT);
            }
            return single;
        }

        /**
         * 连接 Socket
         */
        public void connect() {
            AsyncServer.getDefault().connectSocket(new InetSocketAddress(host, port), new ConnectCallback() {
                @Override
                public void onConnectCompleted(Exception ex, final AsyncSocket socket) {
                    if (ex != null) {
                        Log.e(TAG, "AsyncSocket Exception: " + ex.getMessage());
                        return;
                    }
                    if (socket == null) {
                        closeSocket();
                        connect();
                        return;
                    }
                    asyncSocket = socket;
                    Log.d(TAG, "---> Connected");
                    onConnectCompletedCallBack(socket);
                    sendConnectInfo();
                }
            });
        }

        /**
         * 连接成功后回调
         */
        public void onConnectCompletedCallBack(final AsyncSocket socket) {
            socket.setDataCallback(new DataCallback() {
                @Override
                public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
                    if (bb == null) {
                        return;
                    }
                    String jsonStr = new String(bb.getAllByteArray());
                    if (TextUtils.isEmpty(jsonStr)) {
                        return;
                    }
                    handleConnectSocket(jsonStr);
                    if (onDataCallbackListener != null) {
                        onDataCallbackListener.onDataCallBack(jsonStr);
                    }
                    Log.d(TAG, "Receive : " + jsonStr);
                }
            });

            socket.setClosedCallback(new CompletedCallback() {
                @Override
                public void onCompleted(Exception ex) {
                    isConnected = false;
                    if (ex != null) {
                        Log.e(TAG, "AsyncSocket Exception: " + ex.getMessage());
                        return;
                    }
                    if (onCloseCallbackListener != null) {
                        onCloseCallbackListener.onCloseCallBack();
                    }
                    Log.d(TAG, "---> Closed");
                }
            });

            socket.setEndCallback(new CompletedCallback() {
                @Override
                public void onCompleted(Exception ex) {
                    isConnected = false;
                    if (ex != null) {
                        Log.e(TAG, "AsyncSocket Exception: " + ex.getMessage());
                        return;
                    }
                    if (onEndCallbackListener != null) {
                        onEndCallbackListener.onEndCallBack();
                    }
                    Log.d(TAG, "---> Ended");
                }
            });
        }

        /**
         * 通过 Socket 发送 String
         */
        public boolean writeString(String str) {
            return writeString(null, str);
        }
        public boolean writeString(Context context, String str) {
            if (TextUtils.isEmpty(str)) {
                if (context != null) {
                    ToastTip.show(context, "发送的数据为null");
                }
                return false;
            }
            if (asyncSocket == null) {
                Log.e(TAG, "socket == null");
                return false;
            }
            if (!isConnected && context != null) {
                ToastTip.show(context, "请稍后重试");
            }
            Log.d(TAG, "--------------------------------------------------------");
            Log.d(TAG, "Send: " + str);
            ByteBufferList bbl = new ByteBufferList();
            bbl.add(StringUtil.getByteBuffer(str));
            asyncSocket.write(bbl);
            return isConnected;
        }

        /**
         * Close Socket
         */
        private void closeSocket() {
            if (asyncSocket == null) {
                Log.e(TAG, "socket == null");
                return ;
            }
            Log.d(TAG, "Close Socket");
            asyncSocket.close();
            asyncSocket = null;
        }

        /**
         * 关闭Socket后,释放资源
         */
        public void release() {
            if (mHandler != null) {
                mHandler.removeCallbacks(null);
            }
            closeSocket();
            single = null;
        }

        private OnDataCallbackListener onDataCallbackListener; //Socket 接收数据监听器
        private OnCloseCallbackListener onCloseCallbackListener; //Socket Closed 监听器
        private OnEndCallbackListener onEndCallbackListener; //Socket End 监听器

        public interface OnDataCallbackListener {
            void onDataCallBack(String jsonStr);
        }

        public interface OnCloseCallbackListener {
            void onCloseCallBack();
        }

        public interface OnEndCallbackListener {
            void onEndCallBack();
        }

        public void setOnDataCallbackListener(OnDataCallbackListener onDataCallbackListener) {
            this.onDataCallbackListener = onDataCallbackListener;
        }

        public void setOnCloseCallbackListener(OnCloseCallbackListener onCloseCallbackListener) {
            this.onCloseCallbackListener = onCloseCallbackListener;
        }

        public void setOnEndCallbackListener(OnEndCallbackListener onEndCallbackListener) {
            this.onEndCallbackListener = onEndCallbackListener;
        }
    }

如何使用呢?

1、在Application onCreate()中一句代码初始化并连接:SocketClient.getInstance().connect();
2、在Application onTerminate()中同样一句代码释放资源:SocketClient.getInstance().release();
3、发送String数据:SocketClient.getInstance().writeString(“要发送的String数据”);
4、设置回调监听函数,接收数据并处理(That`s your problem!);

同样这仅仅是简单的封装应用,自己加上重连接机制。具体的通信协议、加密、认证还需和你们的后台开发人员商定。