Java Socket丢包的问题(接收数据中间会穿插很多000000000000)
问题描述
本人菜鸟一枚,为了学习,自己在做一个内网穿透系统,现在有一步是需要客户端把获得的数据返回给Server端
现在的问题是客户端发送的数据,在Server端接收的时候会有**断层**
抽象的来讲,情况大概如下:
客户端发送一个byte[]给Server端,里面的内容转16进制字符串大概是这样
8c4932314489f27cbbcbd35ae4938f3e90fabacab7ef6ff272db444
但是Server端接收的时候,会变成这样
8c4932314489f27cbbcbd35ae4938f3e90000000000000000000000
fabacab7ef6ff272db4440000000000000000000000000000000000
中间有断层
![图片描述][1]
问题出现的环境背景及自己尝试过哪些方法
尝试了一天N多的办法
相关代码
// 请把代码文本粘贴到下方(请勿用图片代替代码)
发送端代码:
@Override
public void run() {
super.run();
try {
int n=-1;
int i=0;
byte[] bytes=new byte[1024];
while (!mSocket.isClosed() && (n=inputStream.read(bytes))!=-1){
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// if (BaseUtility.getVirtualValueLength(bytes)!=bytes.length){
// System.out.println("出现了");
// System.out.println(BaseUtility.toHexString(bytes));
// break;
// }
// i+=n;
// System.out.println("n:"+n);
// System.out.println("i:"+i);
System.out.println(bytes.length);
System.out.println(BaseUtility.toHexString(bytes));
//定义数据头
JSONObject jsonObject=new JSONObject();
jsonObject.put("type",MsgPro.MSG_HEAD_FORWARDING);
jsonObject.put("uid",uid);
//定义数据包
Packet packet=new Packet(jsonObject,bytes);
//发送数据包
packet.Send(socket);
// System.out.println("key:"+key+",转发字节:"+n);
// String sendStr=MsgPro.MSG_HEAD_FORWARDING+","+key;
//
// System.out.println("收到本地项目返回数据");
// System.out.println(new String(content));
//
//
// //发送头部长度
// socket.getOutputStream().write(BaseUtility.intToBytes2(sendStr.getBytes().length));
// System.out.println("头部长度:"+sendStr.getBytes().length);
//
//
//
// //发送包数据长度
// socket.getOutputStream().write(BaseUtility.intToBytes2(content.length));
// System.out.println("数据长度:"+content.length);
//
//
// //发送包头
// socket.getOutputStream().write(sendStr.getBytes());
// System.out.println("头部:"+sendStr);
//
//
// //发送包数据
// socket.getOutputStream().write(content);
// System.out.println("数据:----");
// System.out.println(new String(content));
// socket.getOutputStream().flush();
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
outputStream.close();
inputStream.close();
mSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
数据包是自己封装的,Packet的代码:
package packet;
import com.alibaba.fastjson.JSONObject;
import utility.BaseUtility;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class Packet {
private int Type;
private int HeadLength;
private int BodyLength;
private byte[] Head;
private byte[] Body;
private JSONObject HeadObject;
public Packet(JSONObject headObject, byte[] Body) {
this.HeadObject = headObject;
this.Head=headObject.toString().getBytes();
this.HeadLength=headObject.toJSONString().getBytes().length;
this.Body=Body;
this.BodyLength=Body.length;
}
//读取数据流
public Packet(InputStream inputStream) throws Exception {
byte[] bytesReadHeadLength=new byte[4];
byte[] bytesReadBodyLength=new byte[4];
//读取Head长度
inputStream.read(bytesReadHeadLength);
//读取数据报正文长度
inputStream.read(bytesReadBodyLength);
//判断数据头是否正常,一般来说不会有这么多,日后再改进此方法
if (BaseUtility.byteToInt2(bytesReadHeadLength)>990000 || BaseUtility.byteToInt2(bytesReadBodyLength)>990000){
throw new Exception("【数据报文读取异常】,头部字节长度:"+BaseUtility.byteToInt2(bytesReadHeadLength)+"\n"
+"Body字节长度:"+BaseUtility.byteToInt2(bytesReadHeadLength)
);
}
System.out.println("【接收数据报文正常】,头部字节长度:"+BaseUtility.byteToInt2(bytesReadHeadLength)+"\n"
+"Body字节长度:"+BaseUtility.byteToInt2(bytesReadBodyLength));
this.Head=new byte[BaseUtility.byteToInt2(bytesReadHeadLength)];
this.Body=new byte[BaseUtility.byteToInt2(bytesReadBodyLength)];
//读取Head
inputStream.read(this.Head);
//读取数据报正文 body体
inputStream.read(this.Body);
this.HeadObject=JSONObject.parseObject(new String(this.Head));
System.out.println("接收到的头部内容:\n"+JSONObject.parseObject(new String(this.Head)).toJSONString());
System.out.println("接收到的包体内容:\n"+new String(Body));
// System.out.println(this.HeadObject.toJSONString());
}
//发送数据包
public boolean Send(Socket socket){
try {
OutputStream outputStream=socket.getOutputStream();
//发送Head长度
outputStream.write(BaseUtility.intToBytes2(HeadLength));
System.out.println("发送Head长度:"+HeadLength);
System.out.println("Head内容:"+this.HeadObject.toJSONString());
System.out.println(BaseUtility.toHexString(BaseUtility.intToBytes2(HeadLength)));
System.out.println(BaseUtility.toHexString(BaseUtility.intToBytes2(BodyLength)));
//发送Body长度
outputStream.write(BaseUtility.intToBytes2(BodyLength));
System.out.println("发送Body长度:"+BodyLength);
//发送Head
outputStream.write(Head);
//发送Body
outputStream.write(Body);
//刷新缓存推送数据
outputStream.flush();
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
public int getType() {
return Type;
}
public void setType(int type) {
Type = type;
}
public int getHeadLength() {
return HeadLength;
}
public void setHeadLength(int headLength) {
HeadLength = headLength;
}
public int getBodyLength() {
return BodyLength;
}
public void setBodyLength(int bodyLength) {
BodyLength = bodyLength;
}
public byte[] getHead() {
return Head;
}
public void setHead(byte[] head) {
Head = head;
}
public byte[] getBody() {
return Body;
}
public void setBody(byte[] body) {
Body = body;
}
public JSONObject getHeadObject() {
return HeadObject;
}
public void setHeadObject(JSONObject headObject) {
HeadObject = headObject;
}
}
服务器接收端的代码:
public Runnable socketListen(){
Runnable runnable=new Runnable() {
@Override
public void run() {
while (true){
System.out.println("----------------------");
byte[] bytesReadHeadLength=new byte[4];
byte[] bytesReadBodyLength=new byte[4];
//读取Head长度
try {
inputStream.read(bytesReadHeadLength);
//读取数据报正文长度
inputStream.read(bytesReadBodyLength);
} catch (IOException e) {
e.printStackTrace();
}
if (BaseUtility.byteToInt2(bytesReadHeadLength)==-1){
// System.out.println("无字节");
// throw new IOException("已断开");
}
if (BaseUtility.byteToInt2(bytesReadHeadLength)==0){
// System.out.println("无字节");
// throw new Exception("无字节");
}
System.out.println(BaseUtility.toHexString(bytesReadHeadLength));
System.out.println(BaseUtility.toHexString(bytesReadBodyLength));
//判断数据头是否正常,一般来说不会有这么多,日后再改进此方法
if (BaseUtility.byteToInt2(bytesReadHeadLength)>990000 || BaseUtility.byteToInt2(bytesReadBodyLength)>990000){
System.out.println("【数据报文读取异常】,头部字节长度:"+BaseUtility.byteToInt2(bytesReadHeadLength)+"\n"
+"Body字节长度:"+BaseUtility.byteToInt2(bytesReadBodyLength)
);
}
System.out.println("【数据报文正常】,头部字节长度:"+BaseUtility.byteToInt2(bytesReadHeadLength)+"\n"
+"Body字节长度:"+BaseUtility.byteToInt2(bytesReadBodyLength));
byte[] Head=new byte[BaseUtility.byteToInt2(bytesReadHeadLength)];
byte[] Body=new byte[BaseUtility.byteToInt2(bytesReadBodyLength)];
System.out.println(Head.length);
System.out.println(Body.length);
//读取Head
try {
inputStream.read(Head);
//读取数据报正文 body体
inputStream.read(Body);
System.out.println("|body最后几位|");
String str2 = BaseUtility.toHexString(Body).substring(BaseUtility.toHexString(Body).length()-10, BaseUtility.toHexString(Body).length()) ;
System.out.print(str2);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("接收到包头:"+new String(Head));
JSONObject HeadObject= JSONObject.parseObject(new String(Head));
System.out.println(HeadObject==null?"HeadObject为空":HeadObject.toJSONString());
}
}
};
return runnable;
}
你期待的结果是什么?实际看到的错误信息又是什么?
期望结果:数据不断层接收,不要在中间穿插很多00000,这样数据包的结构就破坏了,感谢各位大佬!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
inputStream.read
是有返回值, 返回值是实际读取的字节数, 不能被忽略!你可以参考一下这个链接
http://www.cnblogs.com/pengyi...