socket编程解决粘包和丢包问题
##socket 丢包粘包解决方式
采用固定头部长度(一般为4个字节),包头保存的是包体的长度
header+body
包头+包体

下面的例子不是按照上图中规定的格式编写的,但是思路都是一样的,先读出一个包头,得到包体的长度,解析出包体
public class SocketServer {
public static void main(String args[]) {
ServerSocket serverSocket;
try {
serverSocket = new ServerSocket();
serverSocket.bind(new InetSocketAddress());
System.out.println("启动服务端~");
while (true) {
Socket socket = serverSocket.accept();
new ReceiveThread(socket).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
static class ReceiveThread extends Thread {
public static final int PACKET_HEAD_LENGTH = ;// 包头长度
private Socket socket;
private volatile byte[] bytes = new byte[];
public ReceiveThread(Socket socket) {
this.socket = socket;
}
//将b数组 下标从begin到end-1的值追加到a数组的后面,并返回
public byte[] mergebyte(byte[] a, byte[] b, int begin, int end) {
byte[] add = new byte[a.length + end - begin];
int i = ;
for (i = ; i < a.length; i++) {
add[i] = a[i];
}
for (int k = begin; k < end; k++, i++) {
add[i] = b[k];
}
return add;
}
@Override
public void run() {
int count = ;
while (true) {
try {
InputStream reader = socket.getInputStream();
{ //这里可以保证正好读取到4个字节的包头
if (bytes.length < PACKET_HEAD_LENGTH) { //【第一次进来,或者经过一次循环bytes的长度被置为0】
byte[] head = new byte[PACKET_HEAD_LENGTH - bytes.length];
int couter = reader.read(head);
if (couter < ) {
continue;
}
bytes = mergebyte(bytes, head, , couter);
if (couter < PACKET_HEAD_LENGTH) {
continue;
}
}
}
// 取出包体长度
byte[] temp = new byte[];
temp = mergebyte(temp, bytes, , PACKET_HEAD_LENGTH);
int bodylength = ByteUtil.byteArrayToInt(temp);// 包体长度
//完整读取一个包
if (bytes.length < bodylength + PACKET_HEAD_LENGTH) {// 不够一个包
byte[] body = new byte[bodylength + PACKET_HEAD_LENGTH - bytes.length];// 剩下应该读的字节(凑一个包)
int couter = reader.read(body);
if (couter < ) {
continue;
}
bytes = mergebyte(bytes, body, , couter);
if (couter < body.length) {
continue;
}
}
//把包体的内容读取出来
byte[] body = new byte[];
body = mergebyte(body, bytes, PACKET_HEAD_LENGTH, bytes.length);
count++;
System.out.println("server receive body: " + count + new String(body));
//为读取下一个包将数组长度重置为空数组,长度为0
bytes = new byte[];
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
public class ClientSocket {
public static void main(String args[]) throws IOException {
System.out.println("启动客户端~");
Socket clientSocket = new Socket();
clientSocket.connect(new InetSocketAddress());
new SendThread(clientSocket).start();
}
static class SendThread extends Thread {
Socket socket;
public SendThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
String reqMessage = "HelloWorl ! from clientsocket this is test half packages!";
for (int i = ; i < ; i++) {
sendPacket(reqMessage+ "u "+ i);
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void sendPacket(String message) {
byte[] contentBytes = message.getBytes();// 包体内容
int contentlength = contentBytes.length;// 包体长度
byte[] headbytes = ByteUtil.intToByteArray(contentlength);// 包头字节数组
byte[] bytes = new byte[headbytes.length + contentlength];// 包=包头+包体
int i = ;
for (i = ; i < headbytes.length; i++) {// 包头
bytes[i] = headbytes[i];
}
for (int j = i, k = ; k < contentlength; k++, j++) {// 包体
bytes[j] = contentBytes[k];
}
try {
OutputStream writer = socket.getOutputStream();
writer.write(bytes);
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public class ByteUtil {
public static void main(String[] args) {
byte[] res = intToByteArray();
System.out.println(byteArrayToInt(res));
}
public static byte[] intToByteArray(int i) {
byte[] result = new byte[];
// 由高位到低位
result[] = (byte) ((i >> ) & 0xFF);
result[] = (byte) ((i >> ) & 0xFF);
result[] = (byte) ((i >> ) & 0xFF);
result[] = (byte) (i & 0xFF);
return result;
}
public static int byteArrayToInt(byte[] bytes) {
int value = ;
// 由高位到低位
for (int i = ; i < ; i++) {
int shift = ( - - i) * ;
value += (bytes[i] & 0x000000FF) << shift;// 往高位游
}
return value;
}
}
转自: https://blog.csdn.net/nongfuyumin/article/details/78298380?utm_source=blogxgwz5
socket编程解决粘包和丢包问题的更多相关文章
- python/socket编程之粘包
python/socket编程之粘包 粘包 只有TCP有粘包现象,UDP永远不会粘包. 首先需要掌握一个socket收发消息的原理 发送端可以是1k,1k的发送数据而接受端的应用程序可以2k,2k的提 ...
- VS2015编译FFMPEG,修改FFmpeg缓冲区大小解决实时流解码丢包问题,FFmpeg错误rtsp流地址卡死的问题,设置超时
之前尝试过很多网上利用Windows编译FFmpeg的文章,都没有办法编译X64位的FFmpeg,有些教程中有专门提到编译64位的FFmpeg需要下载mingw-w64-install,但是编译的过程 ...
- 嵌入式开发之UDP 丢包--- UDP 丢包控制方法
0. 发送端可以,发送五次左右,再Sleep 1.调用recv方法接收端收到数据后,处理数据花了一些时间,处理完后再次调用recv方法,在这二次调用间隔里,发过来的包可能丢失.对于这种情况可以修改接收 ...
- socket编程 TCP 粘包和半包 的问题及解决办法
一般在socket处理大数据量传输的时候会产生粘包和半包问题,有的时候tcp为了提高效率会缓冲N个包后再一起发出去,这个与缓存和网络有关系. 粘包 为x.5个包 半包 为0.5个包 由于网络原因 一次 ...
- Socket编程--TCP粘包问题
TCP是个流协议,它存在粘包问题 产生粘包的原因是: TCP所传输的报文段有MSS的限制,如果套接字缓冲区的大小大于MSS,也会导致消息的分割发送. 由于链路层最大发送单元MTU,在IP层会进行数据的 ...
- day34 基于TCP和UDP的套接字方法 粘包问题 丢包问题
TCP 基于流的协议 又叫可靠性传输协议 通过三次握手 四次挥手 来保证数据传输完毕 缺点效率低 正因为是基于流的协议 所以会出现粘包问题粘包问题:原因一:是应为数据是先发送给操作系统,在操作系统中有 ...
- socket之解决粘包方法
low方法 import socket,subprocess ip_port=('127.0.0.1',8080) s=socket.socket(socket.AF_INET,socket.SOCK ...
- C#中Socket编程解决应用程序直接的通信
using System;using System.Collections.Generic;using System.Linq;using System.Text; using System.Net; ...
- UDP丢包和无序 问题的解决方法
最近在做一个项目,在这之前,做了个验证程序. 发现客户端连续发来1000个1024字节的包,服务器端出现了丢包现象. 纠其原因,是服务端在还未完全处理掉数据,客户端已经数据发送完毕且关闭了. 我用过s ...
随机推荐
- springboot之单元测试
springboot在写完之后,肯定都需要进行单元测试,如下给出一些样例 工程层次结构如图 代码如下: controller: package com.rookie.bigdata.controlle ...
- java.net.ProtocolException:unexpected end of stream
原因:php 给android 写接口出现java.net.ProtocolException:unexpected end of stream,查找android方面原因时发现数据超长 ,发现htm ...
- JS使用cookie实现只出现一次的广告代码效果
我们上网经常会遇到第一次需要登录而之后不用再登录的网站的情况,其实是运用了Cookie 存储 web 页面的用户信息,Cookie 以名/值对形式存储,当浏览器从服务器上请求 web 页面时, 属于该 ...
- [转]原生JS-查找相邻的元素-siblings方法的实现
在针对element的操作里,查找附近的元素是一个不可少的过程,比如在实现tab时,其中的一个div增加了“on”class,其他的去除“on”class.如果用jquery的朋友就肯定不会陌生sib ...
- [DOM基础]offsetHeight,clientHeight,scrollHeight,innerHeight,outerHeight等属性的解释
由于经常搞混这几个属性,所以查找资料总结一下,方便以后翻出来温习. 一.偏移量-以offset开头的 1.offsetHeight:元素在垂直方向上占用的空间大小,像素.包括元素的高度.可见的水平滚动 ...
- AndroidStudio安装、配置、测试
AndroidStudio安装.配置.测试(win7_64bit) 目录 1.概述 2.本文用到的工具 3.安装测试 4.模拟器安装.使用 5.常用配置 6.注事事项 7.相关博文 >>看 ...
- C# RichTextBox 制作文本编辑器
本文利用一个简单的小例子[文本编辑器],讲解RichTextBox的用法,仅供学习分享使用,如有不足之处,还请指正. Windows窗体中的RichTextBox控件用于显示,输入和操作格式化的文本, ...
- Android自定义多宫格解锁控件
在此之前,一直在想九宫格的实现方法,经过一个上午的初步研究终于完成了一个简单的N*N的宫格解锁组件,代码略显粗糙,仅仅做到简单的实现,界面等后期在做优化,纯粹是学习的目的,在算法上有点缺陷,如果有错误 ...
- 不需要再手写 onSaveInstanceState 了,因为你的时间非常值钱
如果你是一个有经验的 Android 程序员,那么你肯定手写过许多 onSaveInstanceState 以及 onRestoreInstanceState 方法用来保持 Activity 的状态, ...
- 算法: 包含min函数的栈
* @Description 包含min函数的栈* @问题:定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1)).* @思路: 1:Stack 类中的p ...