wzltina 2010-11-25 11:07
浏览 864
已采纳

关于java 不能完全读取socket二进制流的问题(数据量越大问题就越严重)

我在java中用socket读取server端发过来的二进制流,从包头前面11个字节中读取包体的字节总数,然后再循环读取包体的字节数,但当server端的数据字节比较大时就不能完全读过来 ,如从server端发送了 3万个字节,这时client端程序就会不能完全读出server端的字节,可能只能读2万多个; 当字节数少于2000 以下时,就基本没有出现过问题。
我把程序贴出来,这段程序有什么问题么?接收大量的数据该如何处理为好?
想了很久,没想明白是怎么回事,望各位不吝赐教!!!

public class SocketService {

private static Socket socket;
private static InputStream is;
private static OutputStream os;
private static BufferedInputStream br;

public static byte[] getReceiveBytes(Catalog catalog,byte[] b) {
    byte[] receive_body_byte = {};
    try {
    socket = new Socket(catalog.getPrivateTcpIp(), Integer.parseInt(catalog.getPrivateTcpIPPort()));

        is = new DataInputStream(socket.getInputStream());
        os = new DataOutputStream(socket.getOutputStream());
        os.write(b);
        br = new BufferedInputStream(is);

        // 包体长度 packlength。
        String packlength = "";

                        // 先收11个字节,函数解析出数据包长度 
        byte[] encry_byte = new byte[11];       
        int sizeHead = br.read(encry_byte);
        for (int m = 0; m < sizeHead; m++) {
            if (m > 6) {
                packlength = packlength + Util.byte2HexStr(encry_byte[m]);
            }
        }
        receive_body_byte = new byte[Integer.parseInt(packlength, 16)];
                         // 接收剩下的字节
        int size = br.read(receive_body_byte);
        //打印接收到的字节
        System.out.println("\n-------接收到的字节总数是-------------- "+receive_body_byte.length);

        os.flush();
        is.close();
        os.close();
        br.close();
    } catch (Exception e) { 
                    System.out.print("**********Socket异常!!!!*********"+e.getMessage());
                    return null;
    }

    return receive_body_byte;
}

========= 上面的程序不知哪里有问题,于是我就又优化了一下,代码如下,但遇到大数据还是不能全读出来===================

       public class SocketService {

private static Socket socket;
private static InputStream is;
private static OutputStream os;
private static BufferedInputStream br;

public static byte[] getReceiveBytes(Catalog catalog,byte[] b) {
    byte[] receive_body_byte = {};
    try {
    socket = new Socket(catalog.getPrivateTcpIp(), Integer.parseInt(catalog.getPrivateTcpIPPort()));

        is = new DataInputStream(socket.getInputStream());
        os = new DataOutputStream(socket.getOutputStream());
        os.write(b);
        br = new BufferedInputStream(is);

        // 包体长度 packlength。
        String packlength = "";

                        // 先收11个字节,函数解析出数据包长度 
        byte[] encry_byte = new byte[11];       
        int sizeHead = br.read(encry_byte);
        for (int m = 0; m < sizeHead; m++) {
            if (m > 6) {
                packlength = packlength + Util.byte2HexStr(encry_byte[m]);
            }
        }
        receive_body_byte = new byte[Integer.parseInt(packlength, 16)];
                            int size = 0
        //  分次取server端的数据,即每次从流中取1024个字节,不足1024就一次取过来
        while(true){
        int a = receive_body_byte.length/1024;

        if(a>=1){
            int last=0;
            Thread.sleep(280);
            for(int i=0;i<a;i++){
                //Thread.sleep(50);
                byte[] btmp = new byte[1024];
                br.read(btmp);
                    getBytes(receive_body_byte,i*1024,btmp);
                    last = last + i*1024;
                    Thread.sleep(100);
                }
                //然后取剩余不足1024个的字节
                int aa = receive_body_byte.length%1024;
                byte[] bmp = new byte[aa];
                //Thread.sleep(200);
                if(aa!=0){
                    br.read(bmp);
                    System.out.println(" aa------------"+aa);
                    p(bmp);
                    Thread.sleep(100);
                    getBytes(receive_body_byte,a*1024,bmp);
                }
                break;
            }else{

                br.read(receive_body_byte);
                break;
            }
        }
        //打印接收到的字节
        System.out.println("\n-------接收到的字节总数是-------------- "+receive_body_byte.length);

        os.flush();
        is.close();
        os.close();
        br.close();
    } catch (Exception e) { 
                    System.out.print("**********Socket异常!!!!*********"+e.getMessage());
                    return null;
    }

    return receive_body_byte;
}
  • 写回答

14条回答 默认 最新

  • enet_java 2010-11-25 16:40
    关注

    类似的问题,我也遇到过,我使用如下代码以后,就没有这个问题了,供你参考,

    // 读取实际的对象内容
    buffer = new byte[objContentleng];
    int nIdx = 0;
    int nTotalLen = buffer.length;
    int nReadLen = 0;

                while (nIdx < nTotalLen)
                {
                    nReadLen = bis.read(buffer, nIdx, nTotalLen - nIdx);
    
                    if (nReadLen > 0)
                    {
                        nIdx = nIdx + nReadLen;
                    }
                    else
                    {
                        break;
                    }
                }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(13条)

报告相同问题?

悬赏问题

  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记