温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Android环境下使用SocketClient

发布时间:2020-07-09 06:45:24 来源:网络 阅读:1271 作者:stevelee_2012 栏目:移动开发

        最近对原来写的SocketClient代码进行优化,从整体架构到具体细节,修改的地方比较多。今天有时间把SocketClient的相关知识整理一下。如果有错误的地方,还望指正!!!


一、整体流程:

Android环境下使用SocketClient

   

 描述如下:

               1.  在Android环境下,SocketClient长连接,需要使用service。

               2.  SocketManagerService是在APK启动时启动。

               3.  SocketManagerService启动时则SocketClientThread也启动。

               4.  View调用SocketManagerServicesendCmd方法发送命令。

               5.  如果SocketClient连接断开,则重新建立连接,并且发送该命令。

               6. 状态返回则通过自定义Listener实现。  


二、预备知识:

 

      1. 判断SocketClient是否与SocketServer连接:

 

        1) . public void sendUrgentData(int value) throws IOException

                源码注释: 

                      Sends the given single byte data which is represented by the lowest octet of {@code value} as "TCP urgent data". 

                翻译:

                      发送给定的代表最低字节码值的单字节数据,作为TCP紧急数据 。   

                个人理解:

                      该方法用于判断SocketClient是否与SocketServer连接。

             

     2.关于SocketClient的超时的理解:

 

         1) . public void connect(SocketAddress remoteAddr, int timeout) throws IOException 

              源码注释:    

                    Connects this socket to the remote host address and port number specified by the 

                    {@code SocketAddress} object with the given timeout. This method will block indefinitely if the timeout is set to zero.

               翻译:

                     在有超时的情况下,socket连接指定地远程主机的地址和端口。如果timeout是0,则方法永远阻塞。      

                    

               个人理解:  

                   该方法的作用是SocketClient与SocketServer之间建立连接时的超时判断。

 

         2). public synchronized void setSoTimeout(int timeout) throws SocketException 

             源码注释:

                   Sets this socket's {@link SocketOptions#SO_TIMEOUT read timeout} in milliseconds.

                   Use 0 for no timeout. To take effect, this option must be set before the blocking method was called.

             翻译:

                   设置socketClient读的超时时间。0表示没有超时。该方法必须在阻塞方法之间调用。   

             个人理解:  

                    InputStream的read方法,在timeout的时间内没有接收到数据,则超时。超时后read方法停止阻塞状态。


三、问题解答  :

1.  如何实现SocketClient的重新连接?


           1). SocketClient设置setSoTime(int timeout) 当超时后,则read停止阻塞,所以线程停止运行。我代码中timeout设置为30分钟。

           2). 在SocketManagerService中实现发送命令的方法,代码如下: 

       

public void sendCameraCmdThread(byte[] cmd) {
          if (cmd == null) return;
            Log.i("TEST","====================================sendCameraCmd");
          try {
               socketClientThread.sendUrgentData();
               socketClientThread.sendCameraCmdThread(cmd);
          } catch (Exception e) {
               //重新连接的代码
               e.printStackTrace();
               socketClientThread = new SocketClientThread();
               socketClientThread.setByteArrCommand(cmd);
               socketClientThread.start();
          }
     }


 2. SocketClient重新连接后,如何重发命令

  因为SocketClient重新连接,所以必须在SocketClient重新连接后才能重发命令。在线程中增加 public void setCommandArr(byte[] cmds) 方法。具体代码如下:             

@Override
public void run() {
    super.run();
    Timer timer = new Timer();
    try {
        if (clientSocket == null) {
            clientSocket = new Socket();
            clientSocket.connect(new InetSocketAddress(IP,PORT),5000);
            if (clientSocket!=null) {
                clientSocket.setReceiveBufferSize(SOCKET_RECV_BUFFER_SIZE);
                clientSocket.setSoTimeout(30*60*1000);
                cameraOutputStream = clientSocket.getOutputStream();
                cameraInputStream = clientSocket.getInputStream();

                if (cameraInputStream!=null) {
                    try {
                        byte[] buffers = new byte[56];
                        int size = 0;
                        timer.schedule(new TimerTask() {
                            @Override
                            public void run() {
                                if(cmdArr!=null) {
                                    for (int i = 0; i < cmdArr.length; i++) {
                                        sendCameraCmdThread(cmdArr[i]);
                                    }
                                }
                            }
                        }, 100);
                        Log.i("TEST","======================>start time");
                        while (clientSocket!=null&&(size = cameraInputStream.read(buffers))!= -1) {
                            Log.i("TEST", "===================> receive msg: " +Utils.bytesToHexString(buffers));
                        }
                    } catch (Exception e) {
                    }
                } else {
                    Log.e("TEST","=================> cameraInputStream is null");
                }
            } else {

            }
        }
    } catch (Exception e) {

    } finally {
        Log.i("TEST","===================>Client Close!");
        if(timer!=null) {
            timer.cancel();
        }
        if (cameraOutputStream!=null) {
            try {
                cameraOutputStream.close();
                cameraOutputStream=null;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (cameraInputStream!=null) {
            try {
                cameraInputStream.close();
                cameraInputStream = null;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (clientSocket!=null) {
            try {
                clientSocket.close();
                clientSocket=null;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

SocketClient重新连接后,则使用Timer延时100毫秒后,则发送命令。这样就能保证发送的命令成功。


附件:http://down.51cto.com/data/2368202
向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI