Socket通信在项目中时有用到,把长连接的相关实例分享一下。
如果要保持一个长连接,Socket代码最好写在一个服务内,避免误杀。
public class SocketService extends Service {
/**
* 心跳标记
*/
private boolean heartFlag = false;
/**
* 是否接受服务器消息
*/
private boolean isReceive = true;
/**
* 线程是否启动
*/
private boolean isStarted;
//初始化Socket
private Socket socket;
//定义一个handler
private Handler mHandler = new Handler(){
public void handleMessage(android.os.Message msg) {
handleMsg(msg);
}
};
/**
* Socket的正常通信数据
*/
public final int HANDLER_MSG_TAG = 0x1001;
/**
* 连接异常handler
*/
public final int EXCEPTION_HANDLER_TAG = 0x1002;
/**
* 主界面提示socket异常,点击可以重新连接
*/
public final int EXCEPTION_SOCKET_TAG=0x1003;
/**
* 定义全局的json
*/
public static String jsonmsg="";
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public void onCreate() {
super.onCreate();
startSocketService();
}
private void startSocketService() {
//判断网络链接的情况下
if (NetUtils.isConnected(getApplicationContext())) {
AcceptThread thread = new AcceptThread();
thread.start();
} else {
sendHandler(EXCEPTION_HANDLER_TAG);
}
}
/**
* Handler 发送消息
*/
public void sendHandler(int tag) {
Message msg = new Message();
msg.what = tag;
mHandler.sendMessage(msg);
}
/**
* 新线程 用于Socket长连接
*/
class AcceptThread extends Thread {
@Override
public void run() {
super.run();
Log.e("%%%%%%%%", "-----------socket线程打开");
if (!isStarted) {
try {
socket = new Socket("IP", 7094); //两个参数,IP和端口号
isStarted = true;
isReceive = true;
heartFlag = true;
socket.setKeepAlive(true);
startMsgLooper(socket);
} catch (UnknownHostException e) {
Log.d("exception",
"断开连接-------UnknownHostException-----%%" + e.getMessage());
} catch (IOException e) {
if (e instanceof SocketException) {
Log.d("exception", "-------SocketException-----%%" + e.getMessage());
}
Log.d("exception",
"断开连接-------IOException-----%%" + e.getMessage());
} catch (Exception e) {
Log.d("exception",
"断开连接-------Exception-----%%" + e.getMessage());
}
}
}
}
/**
* @param client 初始化完成的Socket
* @throws IOException
*/
public void startMsgLooper(Socket client) throws IOException {
String msg = "";
// 这个控制需要你来完成,while中的true
while (isReceive) {
//Socket通过服务器返回的消息
msg = receiveMsg(client);
if (msg != null) {
//首次返回,确认连接成功
if ("{\"state\":200,\"type\":\"confirm\"}".equals(msg)) {
// String为需要传入发送给服务的数据
sendMsg("String", client);
LogUtil.e("asker----",msg); //首次心跳返回
startHeartBeatThread(client);
} else if ("heartbeat".equals(msg)) {
// 在没有数据返回时,持续返回心跳
Log.e("%%%------","heartbeat");
} else {
//Hander机制把数据传出来
Message message = new Message();
message.what = HANDLER_MSG_TAG;
Bundle bundle = new Bundle();
bundle.putString("msg", msg);
message.setData(bundle);
mHandler.sendMessage(message);
}
} else {
//没有接收到心跳时候判断
Log.e("%%%------", "----------我心跳异常,我没收到");
CustomToast.showToast("心跳异常");
}
}
}
/**
* 对socket获取的数据进行读取
* @param in
* @return
* @throws IOException
*/
public static String readLine(PushbackInputStream in) throws IOException {
char buf[] = new char[128];
int room = buf.length;
int offset = 0;
int c;
loop:
while (true) {
switch (c = in.read()) {
case -1:
case '\n':
break loop;
case '\r':
int c2 = in.read();
if ((c2 != '\n') && (c2 != -1)) {
in.unread(c2);
}
break loop;
default:
if (--room < 0) {
char[] lineBuffer = buf;
buf = new char[offset + 128];
room = buf.length - offset - 1;
System.arraycopy(lineBuffer, 0, buf, 0, offset);
}
buf[offset++] = (char) c;
//把截取的heartbeat返回
if (String.copyValueOf(buf, 0, offset).equals("heartbeat")) {
break loop;
}
break;
}
}
if ((c == -1) && (offset == 0))
return null;
return String.copyValueOf(buf, 0, offset);
}
//计时器
private Timer heartBeatTimer;
private TimerTask heartBeatTask;
/**
* 启动心跳线程
*/
private void startHeartBeatThread(final Socket client) {
heartBeatTimer = new Timer();
heartBeatTask = new TimerTask() {
@Override
public void run() {
// Log.e("%%%heart", "心跳----------------" + heartFlag); 心跳日志
try {
if (socket != null && heartFlag) {
sendMsg("heartbeat", client);
}
} catch (IOException e) {
Message message = new Message();
message.what = EXCEPTION_SOCKET_TAG;
mHandler.sendMessage(message);
Log.d("exception", "断开连接-------startHeartBeatThread-----%%"
+ e.getMessage());
} catch (Exception e) {
Message message = new Message();
message.what = EXCEPTION_SOCKET_TAG;
mHandler.sendMessage(message);
Log.d("exception",
"断开连接---startHeartBeatThread----Exception-----%%"
+ e.getMessage());
}
}
};
heartBeatTimer.schedule(heartBeatTask, 1000, 5000);
}
/**
* 发送msg的IO流
* @param string
* @param client
* @throws IOException
*/
private void sendMsg(String string, Socket client) throws IOException {
OutputStream outputStream = client.getOutputStream();
outputStream.write(string.getBytes());
outputStream.flush();
}
/**
* 接受msg的IO流
* @param client
* @return
* @throws IOException
*/
private String receiveMsg(Socket client) throws IOException {
InputStream inputStream = client.getInputStream();
PushbackInputStream pushbackInputStream = new PushbackInputStream(
inputStream);
return readLine(pushbackInputStream);
}
/**
* 处理handler发送的异常情况
* @param msg
*/
public void handleMsg(Message msg) {
switch (msg.what) {
//socket 正常的通信数据,通过广播发送到需要数据的地方
case HANDLER_MSG_TAG:
jsonmsg = msg.getData().getString("msg");
Intent intent = new Intent();
intent.setAction("jsonmsg");
sendBroadcast(intent);
break;
/**
* socket异常时的处理
*/
case EXCEPTION_SOCKET_TAG:
stopSocketService();
// startSocketServer();
// showToast("连接已断开");
break;
default:
break;
}
}
@Override
public void onDestroy() {
stopSocketService();
super.onDestroy();
}
/**
* 关闭socket,2016年1月4日 hgb
*/
public void stopSocketService() {
Log.e("%%%%%%%%", "-----------socket线程被关闭");
isStarted = false;
isReceive = false;
heartFlag = false;
if (heartBeatTask != null) {
heartBeatTask.cancel();
}
if (heartBeatTimer != null) {
heartBeatTimer.cancel();
}
try {
if (socket != null) {
socket.close();
socket = null;
Log.e("%%%%%%%%", "-----------socket.close");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}开启服务:
intentSocket = new Intent(this, SocketService.class);
this.startService(intentSocket);
关闭服务:
this.stopService(intentSocket);