当 NetworkStream.Read(byte[], int, int) 需要返回 -1 时,它会中止()它正在运行
本文关键字:int 运行 byte Read NetworkStream 返回 | 更新日期: 2023-09-27 18:33:47
NetworkStream stream = socket.GetStream();
if (stream.CanRead)
{
while (true)
{
int i = stream.Read(buf, 0, 1024);
result += Encoding.ASCII.GetString(buf, 0, i);
}
}
上面的代码旨在在单独的线程上运行时从TcpClient
检索消息。 Read
方法工作正常,直到它应该返回 -1 以指示没有可读取的内容;相反,它只是终止它正在运行的线程,没有任何明显的原因 - 使用调试器跟踪每个步骤显示它只是在该行之后立即停止运行。
我也尝试用try ... catch
封装它,但没有多大成功。
可能是什么原因造成的?
编辑:我试过了
NetworkStream stream = socket.GetStream();
if (stream.CanRead)
{
while (true)
{
int i = stream.Read(buf, 0, 1024);
if (i == 0)
{
break;
}
result += Encoding.ASCII.GetString(buf, 0, i);
}
}
多亏了@JonSkeet,但问题仍然存在。线程在该read
行终止。
编辑2:我像这样修复了代码,它起作用了。
while (stream.DataAvailable)
{
int i = stream.Read(buf, 0, 1024);
result += Encoding.ASCII.GetString(buf, 0, i);
}
我认为问题很简单,只是没有想得足够彻底。感谢大家的收看!
不,当没有要读取的内容时,Stream.Read
返回 0,而不是 -1:
返回值
读入缓冲区的总字节数。如果当前没有可用的字节数,则此值可以小于请求的字节数,如果已到达流的末尾,则此值可能小于零 (0)。
我的猜测是,实际上,没有抛出异常并且线程没有被中止 - 但它只是永远循环。如果在调试器中单步执行,应该能够看到这一点。无论发生什么,你的"快乐"终止条件永远不会被击中......
由于您正在尝试从流中读取 ASCII 字符,因此请查看以下内容,作为一种可能更简单的方法:
public IEnumerable<string> ReadLines(Stream stream)
{
using (StreamReader reader = new StreamReader(stream, Encoding.ASCII))
{
while (!reader.EndOfStream)
yield return reader.ReadLine();
}
}
虽然这可能不完全是您想要的,但要点是:
- 使用
StreamReader
为您完成所有艰苦的工作 - 使用 while 循环和
!reader.EndOfStream
循环遍历流 - 如果您希望将区块读取到缓冲区中并追加到结果,则仍可以使用
reader.Read(buffer, 0, 1024)
。请注意,这些将是char[]
块而不是byte[]
块,这可能是您想要的。
,它只是在阻塞 - 即等待流的末尾。为了使它返回一个非正数,必须关闭流,即调用方不仅发送了数据,而且关闭了他们的出站套接字。否则,系统无法区分"等待数据包到达"和"流结束"。
如果调用方只发送一条消息,则应在发送后关闭其出站套接字(他们可以保持入站套接字打开以进行回复)。
如果调用方正在发送多条消息,则必须使用成帧方法来读取单个子消息。在基于文本的协议的情况下,这通常意味着"寻找换行符"。