循环直到TcpClient的反应充分阅读 [英] Loop until TcpClient response fully read

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

问题描述

我写了一个简单的TCP客户机和服务器。问题在于客户端。

我有一些麻烦,从服务器读取整个响应。我一定要让线程睡眠,让所有的数据传送。

我试过几次将其转换code到运行,直到服务器完成发送数据的循环。

  //初始化和放大器;连接到客户端
TcpClient的客户端=新的TcpClient();
Console.WriteLine(连接......);
client.Connect(192.168.1.160,9988);

//流串到服务器
输入+ =\ N的;
流STM = client.GetStream();
ASCIIEncoding ASEN =新ASCIIEncoding();
byte []的BA = asen.GetBytes(输入);
stm.Write(BA,0,ba.Length);

//读取来自服务器的响应。
byte []的缓冲区=新的字节[1024];

System.Threading.Thread.Sleep(1000); //咦,为什么我需要等待?

INT读取动作= stm.Read(缓冲液,0,buffer.Length);
响应= Encoding.ASCII.GetString(缓冲液,0,读取动作);
Console.WriteLine(响应字符串:+响应);

client.Close();
 

解决方案

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

然而,由于客户机/服务器交互的性质,此管道不能保证有内容上被读取。客户端和服务器必须同意通过管道发送的内容。

当你把 抽象的.NET 并覆盖其上的插座的理念,为客户端和服务器之间的协议的规定仍然适用;你可以调用<一个href="http://msdn.microsoft.com/en-us/library/system.io.stream.read.aspx"><$c$c>Stream.Read所有你想要的,但如果你的连接到另一侧的插座不发送内容,呼叫只会等到有内容。

这就是为什么协议存在。在其最基本的层面上,他们帮助定义什么是双方之间发送完整的消息。通常情况下,该机制是沿着线的东西:

  • 其中要读取的字节数发送的长度 - prefixed消息的 的消息
  • 字符用来标记消息的结束(这是不太常​​见取决于正被发送的内容时,多个任意的任何部分的消息可以,就越有可能这将被使用)

这是说你不遵守以上;您的来电 Stream.Read 只是说:读1024个字节,而实际上,可能没有1024字节读取。如果是这样的话,调用 Stream.Read 将阻塞,直到一个已经填充。

原因调用 Thread.sleep代码 大概的工作原理是因为当第二流逝,有1024个字节就可以阅读,它不会阻止。

此外,如果你真的想读1024个字节,你不能假设调用 Stream.Read 将填充1024个字节的数据。对于返回值 Stream.Read 方法告诉你多少字节实际读取。如果您的留言需要更多的,那么你需要做额外调用 Stream.Read

乔恩斯基特写了,如果你想有一个样品要做到这一点具体的方式。

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 += "\n";
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.

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:

  • A length-prefixed message where the number of bytes to read is sent before the message
  • A pattern of characters used to mark the end of a message (this is less common depending on the content that is being sent, the more arbitrary any part of the message can be, the less likely this will be used)

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.

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.

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 wrote up the exact way to do this if you want a sample.

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

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