C# 计算TcpClient通过NetworkStream BinaryReader/BinaryWriter传输的字节数
我正在使用围绕C# 计算TcpClient通过NetworkStream BinaryReader/BinaryWriter传输的字节数,c#,network-programming,tcpclient,networkstream,binaryreader,C#,Network Programming,Tcpclient,Networkstream,Binaryreader,我正在使用围绕TcpClient构建的网络协议,使用BinaryReader从底层NetworkStream读取字节(相反,使用BinaryWriter写入) 协议以UTF-8编码传输字符串,并调用reader.ReadString()从流中读取字符串(使用writer.Write(someStr)进行写入) 有没有一种简单的方法来确定从网络流读取(或写入)的字节数,而不必跳转来计算传输字符串的实际字节长度 请注意,BinaryWriter.Write()在字符串的实际字节之前写入一个7位编码的
TcpClient
构建的网络协议,使用BinaryReader
从底层NetworkStream
读取字节(相反,使用BinaryWriter
写入)
协议以UTF-8编码传输字符串,并调用reader.ReadString()
从流中读取字符串(使用writer.Write(someStr)
进行写入)
有没有一种简单的方法来确定从网络流读取(或写入)的字节数,而不必跳转来计算传输字符串的实际字节长度
请注意,BinaryWriter.Write()
在字符串的实际字节之前写入一个7位编码的整数,这使得任何手动计算都更加复杂
还请注意,NetworkStream
不支持Position
属性,因为它抱怨无法Seek
此外,我希望避免在读/写过程中引入必须复制/扫描数据的中介,以免影响整个系统的性能
是否有一种简单、高级的方法可以计算通过网络接口的字节数,而无需手动计算字符串的编码和长度?您可以在networkstream和计算字节数的读卡器之间插入自定义流
这样做不需要复制数据。只需将经过的字节数添加到计数器。对于那些对我如何实现字节计数流感到好奇的人,这里是它的全部荣耀(或耻辱,视情况而定):
使用系统;
使用System.IO;
名称空间流
{
///
///用于跟踪读写字节数的包装器。
///
公共类字节计数流:流
{
私有只读流内部;
私人长字节;
私有长字节读取;
公共字节计数流(流内部)
{
this.inner=内部;
}
公共覆盖无效刷新()
{
内平齐();
}
公共覆盖长寻道(长偏移,参见原始坐标系)
{
抛出新的NotImplementedException();
}
公共覆盖无效设置长度(长值)
{
抛出新的NotImplementedException();
}
公共重写整型读取(字节[]缓冲区、整型偏移量、整型计数)
{
int readBytes=inner.Read(缓冲区、偏移量、计数);
totalBytesRead+=读取字节;
返回readBytes;
}
公共重写无效写入(字节[]缓冲区、整数偏移量、整数计数)
{
写(缓冲区、偏移量、计数);
TotalBytesWrited+=计数;
}
public override bool CanRead=>true;
公共覆盖boolcanseek=>false;
public override bool CanWrite=>true;
公共覆盖长长度
{
得到
{
抛出新的NotImplementedException();
}
}
公共重写长位置{get;set;}
public long TotalBytesWrited=>TotalBytesWrited;
公共长TotalBytesRead=>TotalBytesRead;
}
}
实现将缓冲区传递给底层流,因此实际上不涉及数据复制。这样做您希望实现什么?您可以在networkstream和计算字节数的读取器之间插入自定义流。@usr我只需要知道读取/写入的总字节数-用于报告目的。底层协议堆栈中的某些内容必须知道发送/接收的字节数。。。我想以最简单的方式获得这些信息。你能举出一个例子来说明如何做到这一点吗?有什么具体问题吗?从流派生并以这种方式包装另一个流实例。这难道不需要缓冲数据吗?我不想让事情慢下来。我已经说过不会有缓冲。如果您不认为这是真的,请提供一个为什么会有缓冲的原因。也许您应该开始使用流实现,以便了解它的外观。例如,在Read方法中,您将传入的缓冲区传递给内部流。我说我想要一种简单的方法。虽然创建自定义流并不可怕——你说得对,它比我想象的要简单:—)——但确保它在以前使用
NetworkStream
的所有地方都使用是一个大麻烦。这不是我一直在寻找的简单解决方案,但它是有效的,所以我会接受你的答案。谢谢。Length
看起来破了。这不总是返回0吗?应该扔,位置也是。我几乎用新的简洁6.0语法忽略了它。我需要习惯这一点。而且,我认为,如果不进行处理,这类课程是相当危险的。
using System;
using System.IO;
namespace Streams
{
/// <summary>
/// A wrapper around a <see cref="Stream"/> that keeps track of the number of bytes read and written.
/// </summary>
public class ByteCountingStream : Stream
{
private readonly Stream inner;
private long totalBytesWritten;
private long totalBytesRead;
public ByteCountingStream(Stream inner)
{
this.inner = inner;
}
public override void Flush()
{
inner.Flush();
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
public override int Read(byte[] buffer, int offset, int count)
{
int readBytes = inner.Read(buffer, offset, count);
totalBytesRead += readBytes;
return readBytes;
}
public override void Write(byte[] buffer, int offset, int count)
{
inner.Write(buffer, offset, count);
totalBytesWritten += count;
}
public override bool CanRead => true;
public override bool CanSeek => false;
public override bool CanWrite => true;
public override long Length
{
get
{
throw new NotImplementedException();
}
}
public override long Position { get; set; }
public long TotalBytesWritten => totalBytesWritten;
public long TotalBytesRead => totalBytesRead;
}
}