以下是我的一个代码
用途是读取BufferedInputStream内的数据 
   private String read(BufferedInputStream is)throws Exception
    {
        int readret=is.read();//first char
        int len = is.available();
        byte[] buffer = getByteBuffer(readret,len);
        is.read(buffer,1,len);
        return new String(buffer,"utf-8");
    }因为BufferedInputStream里面是socket.getInputStream()socket类的数据 长度不定。
我目的是 通过available()方法初始一个buffer然后在读取。1. 上面的方法有问题吗?可以一次读取所有数据吗?
2. 上面的方法我在不同机器上运行了,但是结果不一样。
   我都抓包看了 包内数据
   一台抓包 并运行结果 可以一次读取socket内数据。
   另外一台抓包 并运行 结果抓包结果可以看到完整的数据包数据,但是上面运行方法没有读全所有数据。
3. 对于我的需求 是对socket流内每次长度不一的数据进行读取有什么好方法?
   有人可能说用BufferedReader. readLine() 但是网络数据内本身有的\r\n等 也是 我所需要的,需要一次读全。

解决方案 »

  1.   

    用udp好了
    用ObjectInputStream也行,这个可以分"帧",每次长度可以确定
      

  2.   

    ObjectInputStream?我试了下 new ObjectInputStream(socket.getInputStream());结果程序 到这个地方停住了
      

  3.   

    socket.getInputStream();  --是阻塞的用SocketChannel可以设为非阻塞的,一句话说不清。
      

  4.   

    阻塞?那BufferedInputStream(socket.getInputStream());
    就没问题呢?
      

  5.   


    阻塞
      阻塞调用是指调用结果返回之前,当前线程会被挂起。函数只有在得到结果之后才会返回。有人也许会把阻塞调用和同步调用等同起来,实际上他是不同的。对于同 步调用来说,很多时候当前线程还是激活的,只是从逻辑上当前函数没有返回而已。例如,我们在CSocket中调用Receive函数,如果缓冲区中没有数 据,这个函数就会一直等待,直到有数据才返回。而此时,当前线程还会继续处理各种各样的消息。如果主窗口和调用函数在同一个线程中,除非你在特殊的界面操 作函数中调用,其实主界面还是应该可以刷新。socket接收数据的另外一个函数recv则是一个阻塞调用的例子。当socket工作在阻塞模式的时候, 如果没有数据的情况下调用该函数,则当前线程就会被挂起,直到有数据为止。非阻塞
      非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。  对象的阻塞模式和阻塞函数调用
      对象是否处于阻塞模式和函数是不是阻塞调用有很强的相关性,但是并不是一一对应的。阻塞对象上可以有非阻塞的调用方式,我们可以通过一定的API去轮询状 态,在适当的时候调用阻塞函数,就可以避免阻塞。而对于非阻塞对象,调用特殊的函数也可以进入阻塞调用。函数select就是这样的一个例子。
      

  6.   

    对于Socket流来说available是不可信的,因为这个属性的意义并不是指对方发送了多少数据
    而是指在没有阻塞前还可以读取多少数据,也就是这一个数据包对方发送了多少数据。而在Socket发送过程,对方发送的数据是会自动分包的,这个过程不受你控制。
    所以Socket流来说,双方必须先协议总共发送多少字节的数据,再读取指定长度的数据而不用理会available
      

  7.   

    如果你考虑使用ObjectInputStream也是可以的,但是这个时候必须要求对方也使用ObjectOutputStream写数据才可以。而且双方只能new一次这个Stream,以后都使用这个Stream进行数据发送
      

  8.   


    这样设计思路来读取数据正是API是最反对的
    1)上面的方法有问题吗?可以一次读取所有数据吗?
    问题很严重。不要这样来设计程序。能否一次读取所有数据,完全看网络的通信繁忙程度,因而这样设计是不对的。
    2)上面的方法我在不同机器上运行了,但是结果不一样。
    不用抓包,都能知道肯定结果是不定的(即:结果有时相同,有时不一样)
    3) 对于我的需求 是对socket流内每次长度不一的数据进行读取有什么好方法?
    这是一个最基本的网络读取数据的要求,显然楼主是刚入这一行的,对网络通信不熟悉。
    通用的做法(也是网络上最常用的做法是)以网络字节流读取为例:
    你首先与服务器方规定好一个应用层的协议(这是任何网络应用程序在设计之前,首先要做的事)
    针对你的需求,不妨规定(简单些):4个字节表示本次传输的字节长度后跟真正的字节数据
    读取时,你先读4个字节的那个长度,然后再这个长度反复多次读取,直到读到指定个数的字节为止。为加快
    读取性能,可用每次带绥中的流带读(如:缓冲区8K字节)
      

  9.   

    谢谢 学习啦^_^
     3) 对于我的需求 是对socket流内每次长度不一的数据进行读取有什么好方法?的解答
    判断 一套服务器回应数据 是否完整的话
    就要 每次将8K(如您所说)接起来然后 判断?因为 每次数据都长度不一
      

  10.   

    InputStream is=new InputStream();
    byte[] buf=new byte[100];
    int len=is.read(buf);
    System.out.println(new string(buf,o,len));不用缓存试一试!呵呵!刚学这个!试着回答赚点分!
    如果用缓存
    InputStream is=new InputStream();
    BufferedInputStream bis=new BufferedInputStream(is);
    晕下课了!~~过下来补充缓存这的~做个标记~
      

  11.   

    楼主没有理解我的意思。
    我的意思是说:为加快网络通信计取速度,通常都用带缓冲的流(如:8K)去读,这是应该这样做的。
    如何去读呢?代码怎样写?
    很简单:假设是按照上述的应用层协议的约定,则:
    DataInputStream dis=new DataInpuStream(你的那个8K带缓冲的BifferedInputStream);
    先读长度:
    int len=dis.readInt();//4个字节的长度
    然后一个while循环,反复用int hasRead=dis.read(buf),每次累加hasRead[它表示本次读了多少个字节到buf数组中了]直到读到len个字节为止。
    就行了。
      

  12.   

    我是来学习的!楼上的高手是这样的吗?
    DataInputStream dis=new DataInpuStream(is);
    int len=dis.readInt();
    int hasRead=0;
    while(true)
    {
       if(hasRead!=len)
       {
          int hasRead=dis.read(buf);
          hasRead+=hasRead;
       }
       else
         break;
    }