C# 如何从NetworkStream获取所有数据
我试图读取通过TCP/IP连接的机器缓冲区中的所有数据,但我不知道为什么我没有获取所有数据,有些数据丢失了。 这是我正在使用的代码C# 如何从NetworkStream获取所有数据,c#,tcp,tcpclient,tcp-ip,networkstream,C#,Tcp,Tcpclient,Tcp Ip,Networkstream,我试图读取通过TCP/IP连接的机器缓冲区中的所有数据,但我不知道为什么我没有获取所有数据,有些数据丢失了。 这是我正在使用的代码 using (NetworkStream stream = client.GetStream()) { byte[] data = new byte[1024]; int numBytesRead = stream.Read(data, 0, data.Length); if (numBytesRead > 0) {
using (NetworkStream stream = client.GetStream())
{
byte[] data = new byte[1024];
int numBytesRead = stream.Read(data, 0, data.Length);
if (numBytesRead > 0)
{
string str= Encoding.ASCII.GetString(data, 0, numBytesRead);
}
}
请告诉我从机器上获取所有数据缺少什么。
提前感谢。中的此示例演示了如何使用该属性执行此操作:
// Examples for CanRead, Read, and DataAvailable.
// Check to see if this NetworkStream is readable.
if(myNetworkStream.CanRead)
{
byte[] myReadBuffer = new byte[1024];
StringBuilder myCompleteMessage = new StringBuilder();
int numberOfBytesRead = 0;
// Incoming message may be larger than the buffer size.
do{
numberOfBytesRead = myNetworkStream.Read(myReadBuffer, 0, myReadBuffer.Length);
myCompleteMessage.AppendFormat("{0}", Encoding.ASCII.GetString(myReadBuffer, 0, numberOfBytesRead));
}
while(myNetworkStream.DataAvailable);
// Print out the received message to the console.
Console.WriteLine("You received the following message : " +
myCompleteMessage);
}
else
{
Console.WriteLine("Sorry. You cannot read from this NetworkStream.");
}
TCP本身没有任何方法来定义“数据结束”条件。这是应用程序级portocol的职责 例如,请参见请求描述: 客户端请求(在本例中为请求行,仅包含一个标题字段)后接一个空行,因此请求以双换行结束 所以,对于请求端,数据由两个换行序列确定。回应: Content Type指定HTTP消息传输的数据的Internet媒体类型,Content Length以字节为单位指示其长度 响应内容大小在数据之前的标题中指定。
因此,如何对一次传输的数据量进行编码取决于您自己——它可以是数据开头的2或4个字节,保存要读取的总大小,也可以是更复杂的方式(如果需要)。代码的问题是,如果数据大小大于缓冲区大小(在您的情况下为1024字节),您将无法获得所有数据因此,您必须读取循环中的流。然后您可以
写入内存流中的所有数据,直到网络流结束
请尝试以下代码:
using (NetworkStream stream = client.GetStream())
{
while (!stream.DataAvailable)
{
Thread.Sleep(20);
}
if (stream.DataAvailable && stream.CanRead)
{
Byte[] data = new Byte[1024];
List<byte> allData = new List<byte>();
do
{
int numBytesRead = stream.Read(data,0,data.Length);
if (numBytesRead == data.Length)
{
allData.AddRange(data);
}
else if (numBytesRead > 0)
{
allData.AddRange(data.Take(numBytesRead));
}
} while (stream.DataAvailable);
}
}
使用(NetworkStream=client.GetStream())
{
而(!stream.DataAvailable)
{
睡眠(20);
}
if(stream.DataAvailable&&stream.CanRead)
{
字节[]数据=新字节[1024];
List allData=新列表();
做
{
int numBytesRead=stream.Read(数据,0,数据.长度);
if(numBytesRead==data.Length)
{
allData.AddRange(数据);
}
否则如果(numBytesRead>0)
{
allData.AddRange(data.Take(numBytesRead));
}
}while(stream.DataAvailable);
}
}
希望这能有所帮助,它可以防止您错过发送给您的任何数据。在我的场景中,消息本身告诉您后续消息的长度。这是密码
int lengthOfMessage=1024;
string message = "";
using (MemoryStream ms = new MemoryStream())
{
int numBytesRead;
while ((numBytesRead = memStream.Read(MessageBytes, 0, lengthOfMessage)) > 0)
{
lengthOfMessage = lengthOfMessage - numBytesRead;
ms.Write(MessageBytes, 0, numBytesRead);
}
message = Encoding.ASCII.GetString(ms.ToArray(), 0, (int)ms.Length);
}
试试这个:
private string GetResponse(NetworkStream stream)
{
byte[] data = new byte[1024];
using (MemoryStream memoryStream = new MemoryStream())
{
do
{
stream.Read(data, 0, data.Length);
memoryStream.Write(data, 0, data.Length);
} while (stream.DataAvailable);
return Encoding.ASCII.GetString(memoryStream.ToArray(), 0, (int)memoryStream.Length);
}
}
同步方法有时不显示请求主体。使用异步方法稳定地显示请求体
string request = default(string);
StringBuilder sb = new StringBuilder();
byte[] buffer = new byte[client.ReceiveBufferSize];
int bytesCount;
if (client.GetStream().CanRead)
{
do
{
bytesCount = client.GetStream().ReadAsync(buffer, 0, buffer.Length).Result;
sb.Append(Encoding.UTF8.GetString(buffer, 0, bytesCount));
}
while(client.GetStream().DataAvailable);
request = sb.ToString();
}
@George Sondrompilas的答案是正确的,但您可以使用CopyTo函数,而不是自己编写答案,该函数的作用与此相同:
这可能与您显式读取最多1024字节有关吗?@decPL好的,那么我如何读取所有数据?到底缺少什么?流的开始、结束还是随机字节?您能从字节序列中识别流的结尾吗?您知道数据的预期长度吗?@Aik它缺少随机字节。数据长度未知。它可以是任何内容?不,它不能是任何内容。如果不想等到客户机关闭连接,则需要定义协议。否则-继续阅读直到客户端关闭连接。这个例子做什么?NetworkStream.DataAvailable
对于OP来说是否可靠?何时变为false
?当套接字中没有更多数据时,我变为false,为什么不可靠?否。NetworkStream.DataAvailable
为false
仅表示接收器的接收缓冲区中没有数据。这并不意味着发送方已经完成了发送,因此它不能用于实现协议,也不能解决OP的问题。读一下你自己,你说我是对的,他要求读取流中的所有数据。我同意你的看法,他需要实现一个协议,但这不是问题,他问如何读取流中的所有数据。我高度怀疑OP想要的是什么,但你是对的。不,在str中,您将获得在读取时存储在网络流中的整个字符串。您的意思是说缓冲区中的所有可用数据。对吗?在网络流中使用MemoryStream也是一个可能的解决方案:)+1如果您想要使用代码并扩展它的方法,请检查其他答案。尝试调试您使用的代码并了解每一步发生的情况,这可能会对您有所帮助。我在'while(numBytesRead=stream.Read(data,0,data.Length)>0'处遇到错误,无法将bool转换为int,并且当前上下文和代码的最后一行Encoding.ASCII.GetString(ms.ToArray)中不存在buffer
(),0,ms.Length);
小心。此解决方案在使用
部分结束后关闭连接。我将用var readCount=stream.Read(data,0,data.Length);
和memoryStream.Write(data,0,readCount);
分别替换第8行和第9行。这样就不会得到后面的0字节,而转换成“\0”
输出字符串中的空字符。
string request = default(string);
StringBuilder sb = new StringBuilder();
byte[] buffer = new byte[client.ReceiveBufferSize];
int bytesCount;
if (client.GetStream().CanRead)
{
do
{
bytesCount = client.GetStream().ReadAsync(buffer, 0, buffer.Length).Result;
sb.Append(Encoding.UTF8.GetString(buffer, 0, bytesCount));
}
while(client.GetStream().DataAvailable);
request = sb.ToString();
}