NetworkStream.Write/Read in C# [英] NetworkStream.Write/Read in C#

查看:122
本文介绍了NetworkStream.Write/Read in C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我第一次用C#编写一些代码,这需要使用HTTP与网络连接的设备进行对话.不幸的是,设备损坏了,所以我不能使用HttpWebRequest/HttpWebResponse类,因此我必须自己使用TcpClientNetworkStream来进行操作.

我有以下代码:

I''m writing some code in C# for the first time which requires talking to a network attached device using HTTP. Unfortunately the device is broken and so I cannot use the HttpWebRequest/HttpWebResponse classes, so I''m having to do it myself with TcpClient and NetworkStream.

I''ve got the following code:

// make and send the request
byte[] sendBytes = Encoding.ASCII.GetBytes("GET / HTTP/1.1" + Environment.NewLine + Environment.NewLine);
netStream.Write(sendBytes, 0, sendBytes.Length);

// read and display the response
byte[] bytes = new byte[tcpClient.ReceiveBufferSize];
int bytesRead = netStream.Read(bytes, 0, tcpClient.ReceiveBufferSize);
Console.Writeline(bytesRead + " bytes read");
string returnData = Encoding.ASCII.GetString(bytes);
Console.Writeline(returnData);



现在我可以肯定地知道,我的回复应该是191个字节长.但是,我在bytesRead缓冲区中只能得到40个字节.

使它起作用的唯一方法是执行以下操作:



Now I know for certain that my response should be 191 bytes long. However I only get 40 bytes in my bytesRead buffer.

The only way I can make it work is by doing this:

// make and send the request
byte[] sendBytes = Encoding.ASCII.GetBytes("GET / HTTP/1.1" + Environment.NewLine + Environment.NewLine);
netStream.Write(sendBytes, 0, sendBytes.Length);

// sleep while waiting for a complete response
Thread.Sleep(50)

// read and display the response
byte[] bytes = new byte[tcpClient.ReceiveBufferSize];
int bytesRead = netStream.Read(bytes, 0, tcpClient.ReceiveBufferSize);
Console.Writeline(bytesRead + " bytes read");
string returnData = Encoding.ASCII.GetString(bytes);
Console.Writeline(returnData)



显然,这很丑陋,并且对于不同的网络条件并不稳健,因此我想一种避免这种情况的方法.

我已经尝试了诸如在netStream.DataAvailable 上循环并附加任何其他数据之类的各种操作,但这并没有让我更进一步.

除非我有误解,否则NetworkStream文档中的以下句子暗示这种混乱不是必需的:

可以在NetworkStream类的实例上同时执行读写操作,而无需同步.只要有一个用于写操作的唯一线程和一个用于读操作的唯一线程,读和写线程之间就不会出现交叉干扰,并且不需要同步.

有人建议替代方案吗?



Clearly this is ugly and is not robust to different network conditions, so I would like a way to avoid it.

I''ve tried various things like looping on netStream.DataAvailable and appending any further data but this doesn''t get me any further.

Unless I have misinterpreted it, the following sentence from the NetworkStream documentation implies that this kind of messing around isn''t necessary:

Read and write operations can be performed simultaneously on an instance of the NetworkStream class without the need for synchronization. As long as there is one unique thread for the write operations and one unique thread for the read operations, there will be no cross-interference between read and write threads and no synchronization is required.

Will anybody suggest an alternative?

推荐答案

感谢您的回答.我确定传入的消息小于缓冲区大小.我还尝试了MSDN上概述的方法,但该方法对我没有帮助.这就是我在问题中在netStream.DataAvailable上循环并附加任何其他数据"的意思.

我发现有帮助的是,而不是处理原始的传入字节,如果我将NetworkStream包装在StreamReader和StreamWriter中,则在没有Thread.Sleep()的情况下似乎可以正常工作.

我的控制循环无法以这种方式快速运行,因此我不确定读取器/写入器是否确实在帮助我,或者他们是否只是在放慢速度来避免出现竞争状况(正是Thread.Sleep()所做的事情) ).

无论如何,这似乎至少是可靠的.

我的代码现在看起来像这样:

Thanks for your answer. I am sure that the incoming message is smaller than the buffer size. I have also tried the approach which is outlined on MSDN and it did not help me. This is what I meant by "looping on netStream.DataAvailable and appending any further data" in my question.

What I have found helps is rather than handle the raw incoming bytes, if I wrap the NetworkStream in a StreamReader and StreamWriter things seem to work without my Thread.Sleep().

My control loop cannot run as quickly in this manner though so I am not sure whether the reader/writer are actually helping me or whether they are just slowing things down enough to avoid the race condition (exactly what the Thread.Sleep() was doing).

In any case this seems to be robust at least.

My code now looks like this:

StreamReader reader = new StreamReader(netStream);
StreamWriter writer = new StreamWriter(netStream);

// make and send the request
writer.Write("GET / HTTP/1.1" + Environment.NewLine + Environment.NewLine);
writer.Flush();

// read and display the response
string returnData = reader.ReadToEnd();
Console.Writeline(returnData)


我认为您可能需要继续阅读,直到没有更多可用数据为止.远程计算机可能不会在单个数据包中显示整个响应,因此您的代码应考虑到这一事实,并且在拥有整个消息时也应使用响应的内容停止阅读.在此处查看代码示例 [ ^ ]更多信息.
I think you probably need to keep reading until there is no more data available. The remote computer may not present the entire response in a single packet so your code should allow for that fact and also use the contents of the response to stop reading when you have the entire message. Take a look at the sample code here[^] for some more information.


这篇关于NetworkStream.Write/Read in C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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