本人原来是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
android使用websocket保持长连接 后台为nodejs带心跳检测_第1张图片在这里插入图片描述
说了这么多,放代码了nodejs:

//引入nodejs-websocket 如果报错 在cmd里命令:npm install nodejs-websocketvar 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);

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

更多相关文章

  1. Ubuntu共享WiFi(AP)给Android方法【修正版】
  2. android 使用代码方式创建自定义progressBar——自定义控件学习(
  3. Android中外部程序调用方法总结
  4. Android http请求例子、Unicode转UTF-8 java代码收藏
  5. Android SQLite数据库 《第一行代码》
  6. [置顶] Android中数据存储的5种方法

随机推荐

  1. 【Gradle】Android Gradle 插件
  2. Android SDK Tools和Android SDK Platfor
  3. Android 面试题9
  4. Android四大图片缓存框架之-Fresco之init
  5. Android SDK Manager国内无法更新的解决
  6. android/java中短信pdu编码
  7. Android 之WebView
  8. android JNI 学习笔记1
  9. Android深入理解Context--Service中Conte
  10. android捕获全局异常处理,不闪退