最近工作上要用到的通信技术点-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!);
同样这仅仅是简单的封装应用,自己加上重连接机制。具体的通信协议、加密、认证还需和你们的后台开发人员商定。