java socket解决半包、粘包问题

一、java socket出现半包、粘包问题原因及解决见博客:
http://www.cnblogs.com/solq/p/4315763.html
http://bbs.csdn.net/topics/250027309?page=2
http://blog.csdn.net/pi9nc/article/details/17165171
二、java socket半包、粘包问题解决方案
1、以特殊字符串比如/r、/n作为数据的结尾,这样就可以区分数据包了。
2、发送请求包的时候只发送固定长度的数据包,这样在服务端接收数据也只接收固定长度的数据,这种方法效率太低,不太合适频繁的数据包请求。
3、在tcp协议的基础上封装一层数据请求协议,既数据包=数据包长度+数据包内容,这样在服务端就可以知道每个数据包的长度,也就可以解决半包、粘包问题
三、java socket半包、粘包问题重现,代码如下

package org.weir.socket.socketPackage;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;public class SocketTest {public static void main(String[] args) throws IOException, InterruptedException{new SocketServer().start();new SocketClient().start();}static class SocketClient extends Thread{Socket clientSocket = new Socket();public SocketClient() throws IOException{clientSocket.connect(new InetSocketAddress(8089));}public void run(){String reqMessage = "HelloWorld! from clientsocket this is test half packages!";try {for( int i=0;i<10;i++){OutputStream os = clientSocket.getOutputStream();os.write(reqMessage.getBytes());System.out.println("send message "+i+" "+reqMessage);}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally{if (clientSocket != null) {try {clientSocket.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}}static class SocketServer extends Thread{ServerSocket serverSocket;public SocketServer(){try {serverSocket = new ServerSocket();serverSocket.bind(new InetSocketAddress(8089));} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public void run(){int count = 0;Socket socket = null;try {socket = serverSocket.accept();} catch (IOException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}while(true){try {byte[] byteBuffer = new byte[50];StringBuffer receivBuffer = new StringBuffer();InputStream reader = socket.getInputStream();count = reader.read(byteBuffer);if(count>0){receivBuffer.append(new String(byteBuffer,0,count));System.out.println("receive data from client:"+receivBuffer.toString());}count = 0;} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}
执行结果如下:
一共发送了10个包,因为接收的缓冲区是50个字节,所以会出现无法接收到一个完整包的情况,也即出现半包与粘包的情况。
四、java socket解决半包、粘包的问题。
package org.weir.socket.socketPackage;import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
/*** socket解决半包问题  采用包体长度(两字节)+包体内容来拆包* @author weir* 2017年9月19日下午4:31:36*/
public class ClientSocket {public static void main(String args[]) throws IOException {Socket clientSocket = new Socket();clientSocket.connect(new InetSocketAddress(8089));new SendThread(clientSocket).start();}static class SendThread extends Thread {Socket socket;PrintWriter printWriter = null;public SendThread(Socket socket) {this.socket = socket;try {printWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}@Overridepublic void run() {String reqMessage = "HelloWorld! from clientsocket this is test half packages!";for (int i = 0; i < 100; i++) {sendPacket(reqMessage);}if (socket != null) {try {socket.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}public void sendPacket(String message) {
//          byte[] contentBytes = message.getBytes();// 包体内容
//          int contentlength = contentBytes.length;// 包体长度
//          String head = String.valueOf(contentlength);// 头部内容
//          byte[] headbytes = head.getBytes();// 头部内容字节数组
//          byte[] bytes = new byte[headbytes.length + contentlength];// 包=包头+包体
//          int i = 0;
//          for (i = 0; i < headbytes.length; i++) {// 包头
//              bytes[i] = headbytes[i];
//          }
//          for (int j = i, k = 0; k < contentlength; k++, j++) {// 包体
//              bytes[j] = contentBytes[k];
//          }try {OutputStream writer = socket.getOutputStream();
//              writer.write(bytes);writer.write(message.getBytes());writer.flush();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}
package org.weir.socket.socketPackage;import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
/** packet=packetHead+content* 先读出包体长度,再读出包体,不够就一直读*/
public class SocketServer {public static void main(String args[]) {ServerSocket serverSocket;try {serverSocket = new ServerSocket();serverSocket.bind(new InetSocketAddress(8089));while (true) {Socket socket = serverSocket.accept();new ReceiveThread(socket).start();}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}static class ReceiveThread extends Thread {public static final int PACKET_HEAD_LENGTH=2;//包头长度private Socket socket;private volatile byte[] bytes = new byte[0];public ReceiveThread(Socket socket) {this.socket = socket;}public byte[] mergebyte(byte[] a, byte[] b, int begin, int end) {byte[] add = new byte[a.length + end - begin];int i = 0;for (i = 0; i < a.length; i++) {add[i] = a[i];}for (int k = begin; k < end; k++, i++) {add[i] = b[k];}return add;}@Overridepublic void run() {int count =0;while (true) {try {InputStream reader = socket.getInputStream();if (bytes.length < PACKET_HEAD_LENGTH) {byte[] head = new byte[PACKET_HEAD_LENGTH - bytes.length];int couter = reader.read(head);if (couter < 0) {continue;}bytes = mergebyte(bytes, head, 0, couter);if (couter < PACKET_HEAD_LENGTH) {continue;}}// 下面这个值请注意,一定要取2长度的字节子数组作为报文长度,你懂得byte[] temp = new byte[0];temp = mergebyte(temp, bytes, 0, PACKET_HEAD_LENGTH);String templength = new String(temp);int bodylength = Integer.parseInt(templength);//包体长度if (bytes.length - PACKET_HEAD_LENGTH < bodylength) {//不够一个包byte[] body = new byte[bodylength + PACKET_HEAD_LENGTH - bytes.length];//剩下应该读的字节(凑一个包)int couter = reader.read(body);if (couter < 0) {continue;}bytes = mergebyte(bytes, body, 0, couter);if (couter < body.length) {continue;}}byte[] body = new byte[0];body = mergebyte(body, bytes, PACKET_HEAD_LENGTH, bytes.length);count++;System.out.println("server receive body:  " + count+new String(body));bytes = new byte[0];} catch (Exception e) {e.printStackTrace();}}}}
}

结果如下:

client一共发送了100条数据,server端接收到的都是完整的包。

java socket解决半包、粘包问题相关推荐

  1. java nio解决半包 粘包问题

    java nio解决半包 粘包问题 NIO socket是非阻塞的通讯模式,与IO阻塞式的通讯不同点在于NIO的数据要通过channel放到一个缓存池ByteBuffer中,然后再从这个缓存池中读出数 ...

  2. 自定义Udp/Tcp协议,通信协议Socket/WebSocket,IM粘包、分包解决等(2),ProtocolBuffer

    > 自定义Udp/Tcp协议/通信协议(Java/C):自定义构建和解析IM协议消息:IM自定义UDP通信协议   类似于网络通信中的TCPIP协议一般,比较可靠的通信协议往往包含有以下几个组成 ...

  3. java socket分包粘包 代码_分享java中处理socket通信过程中粘包情况的实例代码

    本篇文章主要介绍了java中处理socket通信过程中粘包的情况,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 这两天学习了java中处理socket通信过程中粘包的情况,而且很重要,所以,今天添 ...

  4. 使用包定长FixedLengthFrameDecoder解决半包粘包

    四.使用包定长FixedLengthFrameDecoder解决半包粘包 4.1 试验 由于客户端发给服务器端的是hello server,im a client字符串,该字符串占用24字节,所以在服 ...

  5. Netty解决TCP的粘包和分包(二)

    2019独角兽企业重金招聘Python工程师标准>>> Netty解决TCP的粘包和分包(二) 使用LengthFieldBasedFrameDecoder解码器分包 先看一下这个类 ...

  6. netty 客户端断开 异常处理_netty案例,netty4.1基础入门篇八《NettyClient半包粘包处理》发数据方式》...

    小傅哥 | https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获.专注于原创专题案例编写,目前已完成的专题有:Netty4.x实战专题案例.用Java实现JVM.基于Ja ...

  7. netty半包粘包 处理_老王:Netty到底是个什么鬼?有没有简单的理解方式?

    前语:不要为了读文章而读文章,一定要带着问题来读文章,勤思考. 作者:lyowish    来源:http://1t.click/7RY # 从HTTP说起 有了Netty,你可以实现自己的HTTP服 ...

  8. http之 半包 粘包

    短连接:  连接->传输数据->关闭连接     HTTP是无状态的,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接.     也可以这样说:短连接是指SOCK ...

  9. netty半包粘包 处理_Java NIO 框架 Netty 之美:粘包与半包问题

    一.前言 Netty 是一个可以快速开发网络应用程序的 NIO 框架,它大大简化了 TCP 或者 UDP 服务器的网络编程.Netty 的简易和快速开发并不意味着由它开发的程序将失去可维护性或者存在性 ...

最新文章

  1. 我用python10年后,我发现学python必看这三本书! 1
  2. Ubuntu12 10下安装JDK7
  3. 用python玩转数据慕课答案第四周_大学慕课用Python玩转数据章节测试答案
  4. (王道408考研操作系统)第五章输入/输出(I/O)管理-第一节1:I/O设备的概念和分类
  5. 最全深度学习资源列表!
  6. [Windows编程] 如何判断操作系统是64位还是32位
  7. 输入一个十进制数N,将它转换成R进制数输出(运用递归实现)
  8. c语言的api_为什么C语言依然是必学的编程语言?
  9. idea swagger生成接口文档_.NetCore3.1中使用Swagger生成接口文档
  10. python调用谷歌翻译英文文献pdf_python调用谷歌翻译
  11. XMPP即时通讯协议使用(六)——开发Openfire聊天记录插件
  12. C语言之基本算法34—分解质因数(方法一)
  13. PyTorch搭建LSTM实现多变量多步长时间序列预测(四):多模型滚动预测
  14. MOOCad Visual Analysis of Anomalous Learing Activities in Massive Open Online Courses
  15. 温柔末世,慢慢到来的末日
  16. 虚拟机 Linux root登录
  17. Android 手机设置 Charles 代理,pem 证书安装不上?
  18. 【bat】批处理教程之for的/f参数
  19. AGC自动增益控制概述
  20. 什么是React Hook?

热门文章

  1. 红酒数据探索(Python内置对象)
  2. 对象转二进制--》二进制转对象
  3. Quality control of sequencing data
  4. SVD的原理及python实现——正本清源
  5. 25款很好看的液晶数字字体下载
  6. 为什么少女怀孕越来越普遍
  7. 机器学习考点---过拟合与欠拟合、CNN原理......
  8. 如何用Visio画数据库实体关系图
  9. 《只是为了好玩:Linux之父林纳斯自传》
  10. N1盒子Armbian折腾记