Android环境下使用SocketClient
最近对原来写的SocketClient代码进行优化,从整体架构到具体细节,修改的地方比较多。今天有时间把SocketClient的相关知识整理一下。如果有错误的地方,还望指正!!!
一、整体流程:
描述如下:
1. 在Android环境下,SocketClient长连接,需要使用service。
2. SocketManagerService是在APK启动时启动。
3. SocketManagerService启动时则SocketClientThread也启动。
4. View调用SocketManagerService的sendCmd方法发送命令。
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 octetof {@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 specifiedby the
{@code SocketAddress} object with the given timeout. This methodwill 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中实现发送命令的方法,代码如下:
publicvoidsendCameraCmdThread(byte[]cmd){if(cmd==null)return;Log.i("TEST","====================================sendCameraCmd");try{socketClientThread.sendUrgentData();socketClientThread.sendCameraCmdThread(cmd);}catch(Exceptione){//重新连接的代码e.printStackTrace();socketClientThread=newSocketClientThread();socketClientThread.setByteArrCommand(cmd);socketClientThread.start();}}
2.SocketClient重新连接后,如何重发命令?
因为SocketClient重新连接,所以必须在SocketClient重新连接后才能重发命令。在线程中增加public voidsetCommandArr(byte[] cmds) 方法。具体代码如下:
@Overridepublicvoidrun(){super.run();Timertimer=newTimer();try{if(clientSocket==null){clientSocket=newSocket();clientSocket.connect(newInetSocketAddress(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=newbyte[56];intsize=0;timer.schedule(newTimerTask(){@Overridepublicvoidrun(){if(cmdArr!=null){for(inti=0;i<cmdArr.length;i++){sendCameraCmdThread(cmdArr[i]);}}}},100);Log.i("TEST","======================>starttime");while(clientSocket!=null&&(size=cameraInputStream.read(buffers))!=-1){Log.i("TEST","===================>receivemsg:"+Utils.bytesToHexString(buffers));}}catch(Exceptione){}}else{Log.e("TEST","=================>cameraInputStreamisnull");}}else{}}}catch(Exceptione){}finally{Log.i("TEST","===================>ClientClose!");if(timer!=null){timer.cancel();}if(cameraOutputStream!=null){try{cameraOutputStream.close();cameraOutputStream=null;}catch(IOExceptione){e.printStackTrace();}}if(cameraInputStream!=null){try{cameraInputStream.close();cameraInputStream=null;}catch(IOExceptione){e.printStackTrace();}}if(clientSocket!=null){try{clientSocket.close();clientSocket=null;}catch(IOExceptione){e.printStackTrace();}}}}
在SocketClient重新连接后,则使用Timer延时100毫秒后,则发送命令。这样就能保证发送的命令成功。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。