Java Socket丢包的问题(接收数据中间会穿插很多000000000000)

发布于 2022-09-11 19:45:54 字数 10419 浏览 17 评论 0

问题描述

本人菜鸟一枚,为了学习,自己在做一个内网穿透系统,现在有一步是需要客户端把获得的数据返回给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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

圈圈圆圆圈圈 2022-09-18 19:45:54

inputStream.read是有返回值, 返回值是实际读取的字节数, 不能被忽略!

你可以参考一下这个链接

http://www.cnblogs.com/pengyi...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文