简体   繁体   English

使用BufferedInputStream读取套接字

[英]Socket reading using BufferedInputStream

I'm using Java's BufferedInputStream class to read bytes sent to a socket. 我正在使用Java的BufferedInputStream类来读取发送到套接字的字节。 The data to the socket is HTTP form so generally is a header with defined content-length, then some content. 套接字的数据是HTTP格式,因此通常是具有已定义内容长度的标头,然后是一些内容。

The problem I'm having is that sometimes BufferedInputStream.read() will not read the full amount of data sent to it. 我遇到的问题是有时BufferedInputStream.read()不会读取发送给它的全部数据。 It returns the number of bytes read but this is much less than has been sent. 它返回读取的字节数,但这比发送的要少得多。 I have verified the bytes sent with Wireshark and can confirm the full message is being transmitted.) 我已经验证了Wireshark发送的字节,并且可以确认正在传输完整的消息。)

Sample code below: 示例代码如下:

BufferedInputStream inFromClient = new BufferedInputStream(socket.getInputStream());
int contentLength = getContentLengthFromHeader();    
byte[] b = new byte[contentLength];
int bytesRead = inFromClient.read(b, 0, contentLength);

Once read() is finished sometimes bytesRead is equal to contentLength but on other occasions read() does not seem to read as far as the end of the content. 一旦read()完成,有时bytesRead等于contentLength但在其他情况下read()似乎没有读到内容的结尾。 Does anyone have any ideas on what is happening? 有没有人对正在发生的事情有任何想法? Is Java buffering output? Java缓冲输出? Are there better ways of reading from sockets? 有更好的方法从套接字读取?

You're assuming that read() fills the buffer. 你假设read()填充缓冲区。 Check the Javadoc. 检查Javadoc。 It transfers at least one byte, that's all it says. 它传输至少一个字节,这就是它所说的。

You don't need both a large buffer and a BufferedInputStream. 您不需要大缓冲区和BufferedInputStream. Change the latter to DataInputStream.readFully(). 将后者更改为DataInputStream.readFully().

This is normal behavior for the read() method: you need to keep reading in a loop until read returns -1. 这是read()方法的正常行为:您需要继续读取循环,直到读取返回-1。 (see http://docs.oracle.com/javase/7/docs/api/java/io/BufferedInputStream.html#read(byte[],%20int,%20int)) (参见http://docs.oracle.com/javase/7/docs/api/java/io/BufferedInputStream.html#read(byte[],%20int,%20int))

In general, it happens because the read method is trying to return all the data it can to you before blocking, not all the data you will ever get. 一般情况下,它发生是因为read方法试图在阻塞之前将所有数据返回给你,而不是你将获得的所有数据。

There are a couple of utility methods I frequently use for this sort of thing: (snipped out of context - note that I am not the author of the channelCopy method, but the source is attributed) 我经常使用一些实用方法来处理这类事情:(剪掉了上下文 - 注意我不是channelCopy方法的作者,但是源是归因的)

   /**
    * Efficiently copy from an InputStream to an OutputStream; uses channels and 
    * direct buffering for a faster copy than oldCopy. 
    * @param in - non-null readable inputstream
    * @param out - non-null writeable outputstream
    * @throws IOException if unable to read or write for some reason.
    */
   public static void streamCopy(InputStream in, OutputStream out) throws IOException {
      assert (in != null);
      assert (out != null);
      ReadableByteChannel inChannel = Channels.newChannel(in);
      WritableByteChannel outChannel = Channels.newChannel(out);
      channelCopy(inChannel, outChannel);
   }

   /**
    * Read the *BINARY* data from an InputStream into an array of bytes. Don't 
    * use this for text.
    * @param is - non-null InputStream
    * @return a byte array with the all the bytes provided by the InputStream 
    * until it reaches EOF.
    * @throws IOException 
    */
   public static byte[] getBytes(InputStream is) throws IOException{
      ByteArrayOutputStream os = new ByteArrayOutputStream();
      streamCopy(is, os);
      return os.toByteArray();
   }


   /**
    * A fast method to copy bytes from one channel to another; uses direct 16k 
    * buffers to minimize copies and OS overhead.
    * @author http://thomaswabner.wordpress.com/2007/10/09/fast-stream-copy-using-javanio-channels/
    * @param src - a non-null readable bytechannel to read the data from
    * @param dest - a non-null writeable byte channel to write the data to
    */   
   public static void channelCopy(final ReadableByteChannel src, final WritableByteChannel dest) throws IOException {
      assert (src != null);
      assert (dest != null);
      final ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024);
      while (src.read(buffer) != -1) {
         // prepare the buffer to be drained
         buffer.flip();
         // write to the channel, may block
         dest.write(buffer);
         // If partial transfer, shift remainder down
         // If buffer is empty, same as doing clear()
         buffer.compact();
      }

      // EOF will leave buffer in fill state
      buffer.flip();

      // make sure the buffer is fully drained.
      while (buffer.hasRemaining()) {
         dest.write(buffer);
      }
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 BufferedInputStream 读取文件 - reading file using BufferedInputStream 网络套接字和文件读取中的BufferedInputStream用例? - BufferedInputStream use cases in network Socket and File Reading? 使用BufferedInputStream从服务器读取音频 - Using a BufferedInputStream for reading audio from server 套接字使用BufferedOutputStream / BufferedInputStream接收伪数据随机 - Socket using BufferedOutputStream/BufferedInputStream receives bogus data random 如何使用BufferedInputStream从套接字检测输入流的结尾? - How to detect end of Input Stream from Socket using BufferedInputStream? 从BufferedInputStream读取byte [] - Reading byte[] from BufferedInputStream 使用BufferedInputStream读取大文件时,Java文件IO被截断 - Java file IO truncated while reading large files using BufferedInputStream 使用BufferedInputStream获取数据 - getting data using BufferedInputStream 为什么 BufferedInputStream(InputStream in, int bufSize) 在使用 mark() 时没有从 inputStream 中读取 bufSize 块中的数据? - Why BufferedInputStream(InputStream in, int bufSize) is not reading data in chunks of bufSize from the inputStream while using mark()? BufferedInputStream将byte []通过Socket发送到数据库 - BufferedInputStream into byte[] to be send over a Socket to a Database
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM