最近有点忙,博客没有定期跟新,抽时间记录下最近工作上要用到的通信技术点-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有超过2500多人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!);

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