http://blog.sina.com.cn/s/blog_4ad7c2540101lep1.html
先说明一下粘包的概念: 发送时是两个单独的包、两次发送,但接收时两个包连在一起被一次接收到。
在以前 WinCE 下 Socket 编程,确实也要处理粘包的问题,没想到在 Android 下也遇到了。
首先想从发送端能否避免这样的问题,例如: (1) 调用强制刷数据完成发送的函数;(2) 设置发送超时。
1 先试了调用 flush() 函数,但运行后现象依旧
2 设置发送超时是 Windows 平台的做法,但在 Android 平台下是否有类似的设置呢?
查看 Socket 类的实现代码:java.net.socket socket.class 文件后发现,还是有函数可以完成这样的设置的。请看如下函数和变量的说明:
-
-
-
- public void setTcpNoDelay(boolean on) throws SocketException {
- checkOpenAndCreate(true);
- impl.setOption(SocketOptions.TCP_NODELAY, Boolean.valueOf(on));
- }
和
-
-
-
-
-
-
- public static final int TCP_NODELAY = 1;
一般情况下,只需要调用如下的代码即可:
- public Socket clientSocket = null;
-
- clientSocket = new Socket("172.25.103.1",12589);
不用做任何设置就可以完成与服务器/客户端的通讯,刚开始我也是这样做的。所以,遇到了上面的问题。
-
-
- clientSocket.setTcpNoDelay(true);
看以下较完整的 Socket 初始化与设置过程:
-
- try {
-
-
- Socket clientSocket = new Socket("172.25.103.1",12589);
-
-
- clientSocket.setSoTimeout(5000);
-
-
- clientSocket.setTcpNoDelay(true);
-
- clientSocket.setSoLinger(true, 30);
-
- clientSocket.setSendBufferSize(4096);
-
- clientSocket.setReceiveBufferSize(4096);
-
-
- clientSocket.setKeepAlive(true);
-
- OutputStream osSend = clientSocket.getOutputStream();
- OutputStreamWriter osWrite = new OutputStreamWriter(osSend);
- BufferedWriter bufWrite = new BufferedWriter(osWrite);
-
- clientSocket.setOOBInline(true);
-
- clientSocket.sendUrgentData(0x44);
-
-
-
- bufWrite.write("Login|LeoZheng,0603 \r\n\r\n");
-
- bufWrite.flush();
- }
- catch (UnknownHostException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- try {
-
-
- if(true == serverSocket.isConnected() && false == serverSocket.isClosed()) {
-
- InputStream isRead = serverSocket.getInputStream();
-
- byte[] buffer = new byte[isRead.available()];
-
- isRead.read(buffer);
-
- String responseInfo = new String(buffer);
-
- Log.i("Socket Server", responseInfo);
- }
-
- serverSocket.close();
- }
- catch (UnknownHostException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- try {
- Socket serverSocket = new Socket();
-
- serverSocket.connect(new InetSocketAddress("172.25.103.1",12589));
-
-
- serverSocket.close();
- }
- catch (UnknownHostException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
最后说明一点: 无论 Socket 如何设置,接收方是一定要处理粘包的问题的。即在接收时,对接收到的数据进行分析,看是否存在数据不全或粘包的现象。