Android进阶——Socket长连接通信实例

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);





  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值