Ada*_*dam 5 java sockets http bufferedinputstream
我正在使用Java的BufferedInputStream
类来读取发送到套接字的字节.套接字的数据是HTTP格式,因此通常是具有已定义内容长度的标头,然后是一些内容.
我遇到的问题是有时BufferedInputStream.read()
无法读取发送给它的全部数据.它返回读取的字节数,但这比发送的要少得多.我已经验证了Wireshark发送的字节,并且可以确认正在传输完整的消息.)
示例代码如下:
BufferedInputStream inFromClient = new BufferedInputStream(socket.getInputStream());
int contentLength = getContentLengthFromHeader();
byte[] b = new byte[contentLength];
int bytesRead = inFromClient.read(b, 0, contentLength);
Run Code Online (Sandbox Code Playgroud)
一旦read()完成,有时bytesRead
等于contentLength
但在其他情况下read()似乎不会读到内容的结尾.有没有人对正在发生的事情有任何想法?Java缓冲输出?有更好的方法从套接字读取?
这是 read() 方法的正常行为:您需要继续循环读取,直到 read 返回 -1。(请参阅http://docs.oracle.com/javase/7/docs/api/java/io/BufferedInputStream.html#read(byte[],%20int,%20int))
一般来说,发生这种情况是因为 read 方法试图在阻塞之前将所有数据返回给您,而不是您将获得的所有数据。
我经常使用一些实用方法来处理此类事情:(断章取义 - 请注意,我不是 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);
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
6060 次 |
最近记录: |