我是靠谱客的博主 端庄河马,最近开发中收集的这篇文章主要介绍android使用websocket保持长连接 后台为nodejs带心跳检测,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

本人原来是java工程师,但是最近没事就干起了android的活,我的具体需求是android使用websocket保持长连接 后台为nodejs 好了 不多说 开撸

nodejs方面使用的是nodejs-websocket,而不是http+ws+socket.io,使用后者在我的android代码会有bug:流意外断开(下图)java.io.IOException: unexpected end of stream on Connection 总之就是连接不上在这里插入图片描述
为解决这个bug,困扰了我很久 查了很多资料 都是如下两图两种方法 还是不能解决 所以我就把想法放到了nodejs中 不使用socket.io 使用nodejs-websocket
在这里插入图片描述在这里插入图片描述
说了这么多,放代码了nodejs:

//引入nodejs-websocket 如果报错 在cmd里命令:npm install nodejs-websocket
var ws= require("nodejs-websocket");  
//广播通知方法 可有可无
const broadcast = (server, info) => {
  console.log('broadcast', info)
  server.connections.forEach(function(conn) {
    conn.sendText(JSON.stringify(info))
  })
}
var server = ws.createServer(function(conn){
	
     //从前端收到信息
    conn.on("text", function (str) {
		//发送消息使用 conn.send("发送消息:"+str);
		broadcast(server,str);  //广播通知收到的消息
   });

    conn.on("close", function (code, reason ) {
         console.log("退出了连接=========》close");
     });

    conn.on("error", function (code, reason) {
         console.log("异常关闭");
    });
}).listen(3000);

android方面代码:

  • InitSocketThread.java 我们在线程里执行连接操作
package com.Piggysnow.RtcView.util;


import android.os.Handler;
import android.support.annotation.Nullable;
import android.util.Log;

import com.Piggysnow.RtcView.MediaUtil;
import com.Piggysnow.RtcView.service.BackService;

import java.io.IOException;
import java.net.UnknownHostException;
import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;

public class InitSocketThread extends Thread{

    BackService service;
    Handler serviceHandler;
    public InitSocketThread(){}
    public InitSocketThread(BackService service,Handler handler)
    {
        this.service = service;
        this.serviceHandler=handler;
    }
    @Override
    public void run() {
        super.run();
        try {
            initSocket();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 心跳检测时间
     */
    private static final long HEART_BEAT_RATE = 15 * 1000;//每隔15秒进行一次对长连接的心跳检测
    private static final String WEBSOCKET_HOST_AND_PORT = "ws://192.168.8.104:3000";//可替换为自己的主机名和端口号
    public static WebSocket mWebSocket;
    // 初始化socket
    public void initSocket() throws UnknownHostException, IOException {

        Log.e("INITSOCKET", "initsocket in");
        OkHttpClient client = new OkHttpClient.Builder().readTimeout(5000, TimeUnit.MILLISECONDS).connectTimeout(6000,TimeUnit.MINUTES).build();
        Request request = new Request.Builder()
                .url(WEBSOCKET_HOST_AND_PORT).build();
        Log.e("INITSOCKET", request.url().uri().toString());
        client.newWebSocket(request, new WebSocketListener() {
            @Override
            public void onOpen(WebSocket webSocket, Response response) {//开启长连接成功的回调
                super.onOpen(webSocket, response);
                Log.e("INITSOCKET", "initsocket onOpen");
                mWebSocket = webSocket;
                mWebSocket.send("MyId?id=123456");  //向服务器发送id
            }

            @Override
            public void onMessage(WebSocket webSocket, String text) {//接收消息的回调
                super.onMessage(webSocket, text);
                Log.e("SENDTEXT", text);  //输入消息
            }

            @Override
            public void onMessage(WebSocket webSocket, ByteString bytes) {
                super.onMessage(webSocket, bytes);
            }

            @Override
            public void onClosing(WebSocket webSocket, int code, String reason) {
                super.onClosing(webSocket, code, reason);
            }

            @Override
            public void onClosed(WebSocket webSocket, int code, String reason) {
                Log.e("INITSOCKET", "initsocket onClosed");
                super.onClosed(webSocket, code, reason);
            }

            @Override
            public void onFailure(WebSocket webSocket, Throwable t, @Nullable Response response) {//长连接连接失败的回调
                mWebSocket=webSocket;
                Log.e("INITSOCKET", "initsocket onFailure");
                super.onFailure(webSocket, t, response);
                t.printStackTrace();
            }
        });
        mHandler.postDelayed(heartBeatRunnable, HEART_BEAT_RATE);//开启心跳检测
    }


     private static long sendTime = 0L;
    // 发送心跳包
    private static Handler mHandler = new Handler();
    private static Runnable heartBeatRunnable = new Runnable() {
        @Override
        public void run() {
            if (System.currentTimeMillis() - sendTime >= HEART_BEAT_RATE) {
                if(mWebSocket==null)
                {
                    mHandler.postDelayed(this, HEART_BEAT_RATE);//每隔一定的时间,对长连接进行一次心跳检测
                    return;
                }
                boolean isSuccess = mWebSocket.send("");//发送一个空消息给服务器,通过发送消息的成功失败来判断长连接的连接状态
                if (!isSuccess) {//长连接已断开
                    mHandler.removeCallbacks(heartBeatRunnable);
                    mWebSocket.cancel();//取消掉以前的长连接
                    new InitSocketThread().start();//创建一个新的连接
                } else {//长连接处于连接状态

                }
                sendTime = System.currentTimeMillis();
            }
            mHandler.postDelayed(this, HEART_BEAT_RATE);//每隔一定的时间,对长连接进行一次心跳检测
        }
    };
}

  • BackService
package com.Piggysnow.RtcView.service;


import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;

import com.Piggysnow.RtcView.util.InitSocketThread;

public class BackService extends Service {


    protected Handler handler=new Handler();

    @Override
    public void onCreate() {
        super.onCreate();
        Log.e("INIT", "Backserver init on create");
        new InitSocketThread(this,handler).start();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new MyBinder();
    }

    public class MyBinder extends Binder {
        public BackService getMyService(){
            return BackService.this;
        }
    }
    /**
     * 在Service中定义这个方法,用于测试
     * @return
     */
    public String getAuthorName(){
        return "guchuanhang";
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (InitSocketThread.mWebSocket != null) {
            InitSocketThread.mWebSocket.close(1000, null);
        }
    }

    public static void main(String[] args) {
        BackService service=new BackService();
        service.onCreate();
    }
}

  • Activity类中需要新增的代码(记住是新增)
 BackService myService=null;
    ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            myService= ((BackService.MyBinder) service).getMyService();
            String authorName = myService.getAuthorName();
            Toast.makeText(UnityPlayerActivity.this, "author name is: " + authorName,
                    Toast.LENGTH_LONG).show();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
        }

    };
  • Activity类onCreate方法中需要新增的代码(记住是新增)
Intent myServiceIntent = new Intent(UnityPlayerActivity.this, BackService.class);
        bindService(myServiceIntent, mServiceConnection,
                Context.BIND_AUTO_CREATE);

然后就到这里结束了 希望大家能够连接成功!!!欢迎大家评论

最后

以上就是端庄河马为你收集整理的android使用websocket保持长连接 后台为nodejs带心跳检测的全部内容,希望文章能够帮你解决android使用websocket保持长连接 后台为nodejs带心跳检测所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(48)

评论列表共有 0 条评论

立即
投稿
返回
顶部