Android环境下使用SocketClient

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


一、整体流程:

wKiom1ftj6fzlPcdAAB3-wJZrrU347.png-wh_50

   

 描述如下:

               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中实现发送命令的方法,代码如下: 

       

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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) 方法。具体代码如下:             

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
@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毫秒后,则发送命令。这样就能保证发送的命令成功。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值