使用套接字时,“流结束”是什么意思 [英] What does 'end of stream' mean when working with sockets

查看:186
本文介绍了使用套接字时,“流结束”是什么意思的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用Java中的套接字时,如何在开始处理之前判断客户端是否已完成所有(二进制)数据的发送。例如:

When working with Sockets in Java, how can you tell whether the client has finished sending all (binary) data, before you could start processing them. Consider for example:

istream = new BufferedInputStream (socket.getInputStream());
ostream = new BufferedOutputStream(socket.getOutputStream());

byte[] buffer = new byte[BUFFER_SIZE];

int count;
while(istream.available() > 0 && (count = istream.read(buffer)) != -1)
{
    // do something..
}

// assuming all input has been read
ostream.write(getResponse());       
ostream.flush();

我在SO上读过类似帖子,例如 this ,但找不到确定的答案。虽然上面的解决方案有效,但我的理解是,您永远无法确定客户端是否已完成所有数据的发送。例如,如果客户端套接字发送了一些数据块,然后阻止等待来自另一个数据源的数据,然后它可以发送更多数据,那么上面的代码可能很好地假设客户端已经完成了所有数据的发送,因为istream.available()将为当前字节流返回0。

I've read similar posts on SO such as this, but couldn't find a conclusive answer. While my solution above works, my understanding is that you can never really tell if the client has finished sending all data. If for instance the client socket sends a few chunks of data and then blocks waiting for data from another data source before it could send more data, the code above may very well assume that the client has finished sending all data since istream.available() will return 0 for the current stream of bytes.

推荐答案

是的,你是对的 - 使用 available()这样不可靠。就个人而言,我很少使用 available()。如果你想阅读直到你到达的末尾(根据问题标题),继续调用 read()直到它返回 - 1。这很容易。如果您不想要流的结束,那么硬位就是服务器此刻想要发送给您的内容。

Yes, you're right - using available() like this is unreliable. Personally I very rarely use available(). If you want to read until you reach the end of the stream (as per the question title), keep calling read() until it returns -1. That's the easy bit. The hard bit is if you don't want the end of the stream, but the end of "what the server wants to send you at the moment."

作为其他人说,如果你需要通过套接字进行对话,你必须让协议解释数据完成的位置。就个人而言,我更喜欢消息令牌结束解决方案的长度前缀解决方案 - 它通常可以使阅读代码更加简单。但是,它可以使编写代码更难,因为您需要在发送任何内容之前计算出长度。如果您可以发送大量数据,这会很痛苦。

As the others have said, if you need to have a conversation over a socket, you must make the protocol explain where the data finishes. Personally I prefer the "length prefix" solution to the "end of message token" solution where it's possible - it generally makes the reading code a lot simpler. However, it can make the writing code harder, as you need to work out the length before you send anything. This is a pain if you could be sending a lot of data.

当然,您可以混合和匹配解决方案 - 特别是,如果您的协议同时处理文本和二进制数据,我会强烈推荐长度前缀字符串而不是空终止它们(或类似的东西)。如果您可以将解码器传递给一个完整的字节数组并只返回一个字符串,那么解码字符串数据往往会容易得多 - 例如,您不必担心读取字符的一半。您可以将此作为协议的一部分使用,但仍然具有数据结束记录的整体记录(或任何您正在传输的记录),以便读者处理数据并做出响应。

Of course, you can mix and match solutions - in particular, if your protocol deals with both text and binary data, I would strongly recommend length-prefixing strings rather than null-terminating them (or anything similar). Decoding string data tends to be a lot easier if you can pass the decoder a complete array of bytes and just get a string back - you don't need to worry about reading to half way through a character, for example. You could use this as part of your protocol but still have overall "records" (or whatever you're transmitting) with an "end of data" record to let the reader process the data and respond.

当然,如果你不能控制协议,所有这些协议设计都没有实际意义:(

Of course, all of this protocol design stuff is moot if you're not in control of the protocol :(

这篇关于使用套接字时,“流结束”是什么意思的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆