循环直到 TcpClient 响应完全读取 [英] Loop until TcpClient response fully read

查看:21
本文介绍了循环直到 TcpClient 响应完全读取的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个简单的 TCP 客户端和服务器.问题出在客户身上.

I have written a simple TCP client and server. The problem lies with the client.

我在读取来自服务器的整个响应时遇到了一些问题.我必须让线程休眠以允许发送所有数据.

I'm having some trouble reading the entire response from the server. I must let the thread sleep to allow all the data be sent.

我已经尝试了几次将这段代码转换成一个循环,直到服务器完成发送数据.

I've tried a few times to convert this code into a loop that runs until the server is finished sending data.

// Init & connect to client
TcpClient client = new TcpClient();
Console.WriteLine("Connecting.....");
client.Connect("192.168.1.160", 9988);

// Stream string to server
input += "
";
Stream stm = client.GetStream();
ASCIIEncoding asen = new ASCIIEncoding();
byte[] ba = asen.GetBytes(input);
stm.Write(ba, 0, ba.Length);

// Read response from server.
byte[] buffer = new byte[1024];

System.Threading.Thread.Sleep(1000); // Huh, why do I need to wait?

int bytesRead = stm.Read(buffer, 0, buffer.Length);
response = Encoding.ASCII.GetString(buffer, 0, bytesRead);
Console.WriteLine("Response String: "+response);

client.Close();

推荐答案

建立在套接字之上的流的本质是你有一个开放的管道来传输和接收数据,直到套接字关闭.

The nature of streams that are built on top of sockets is that you have an open pipeline that transmits and receives data until the socket is closed.

但是,由于客户端/服务器交互的性质,此管道并不总能保证其上有可供读取的内容.客户端和服务器必须同意通过管道发送内容.

However, because of the nature of client/server interactions, this pipeline isn't always guaranteed to have content on it to be read. The client and server have to agree to send content over the pipeline.

当您使用 Stream .NET 中的抽象 并将其覆盖在套接字的概念上,客户端和服务器之间的协议要求仍然适用;你可以调用 Stream.Read 所有你想要的,但如果你的 Stream 在另一端连接的套接字没有发送内容,调用将等待直到有内容.

When you take the Stream abstraction in .NET and overlay it on the concept of sockets, the requirement for an agreement between the client and server still applies; you can call Stream.Read all you want, but if the socket that your Stream is connected to on the other side isn't sending content, the call will just wait until there is content.

这就是协议存在的原因.在最基本的层面上,它们帮助定义在两方之间发送的完整消息是什么.通常,该机制类似于:

This is why protocols exist. At their most basic level, they help define what a complete message that is sent between two parties is. Usually, the mechanism is something along the lines of:

  • 长度为前缀的消息,其中要读取的字节数在消息之前发送
  • 一种用于标记消息结尾的字符模式(这不太常见,具体取决于发送的内容,消息的任何部分越随意,使用的可能性就越小)

也就是说你没有遵守上述规定;您对 Stream.Read 的调用只是说读取 1024 个字节",而实际上可能没有 1024 个字节要读取.如果是这种情况,对 Stream.Read 的调用将被阻塞,直到它被填充.

That said you aren't adhering to the above; your call to Stream.Read is just saying "read 1024 bytes" when in reality, there might not be 1024 bytes to be read. If that's the case, the call to Stream.Read will block until that's been populated.

调用 Thread.Sleep 的原因 可能有效是因为随着时间的流逝,Stream 上有 1024 个字节可供读取并且不会阻塞.

The reason the call to Thread.Sleep probably works is because by the time a second goes by, the Stream has 1024 bytes on it to read and it doesn't block.

此外,如果您真的想读取 1024 字节,则不能假设对 Stream.Read 的调用将填充 1024 字节的数据.Stream.Read 方法的返回值告诉您实际读取了多少字节.如果您需要更多信息,则需要对 Stream.Read 进行额外调用.

Additionally, if you truly want to read 1024 bytes, you can't assume that the call to Stream.Read will populate 1024 bytes of data. The return value for the Stream.Read method tells you how many bytes were actually read. If you need more for your message, then you need to make additional calls to Stream.Read.

Jon Skeet 写了执行此操作的确切方法(如果您需要样本).

这篇关于循环直到 TcpClient 响应完全读取的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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