- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试构建具有持久 TCP 连接的可扩展 服务器应用程序。我使用的序列化库是同步的,将其转换为APM会造成很大的开销(我已经测试过了)。
数据包的格式始终是数据包 ID 的一个字节,后跟几个 header 字段和有效负载。我在想,如果我创建了一个异步方法,例如:
public async Task<Packet> Deserialize(NetworkStream stream)
{
//Omitting parameters for the methods below for simplicity.
var id = await stream.ReadAsync();
var size = stream.Read();
//Read the rest of the fields synchronously and deserialize.
}
Read
其中之一需要太多时间(由于 TCP 碎片例如)?ReadAsync
读取数据包的所有字节(大小是 header 中的第二个字段),然后同步反序列化它们 - 因为它是一个非阻塞操作 - 但这迫使我将有效负载反序列化上下文与 header 的反序列化上下文分开,这将导致我编写大量重复代码。如果上述问题的答案是肯定的,是否还有更可行的解决方案?最佳答案
Will I risk to cause starvation for other sockets
如果对于“socket”,我们读作“thread”,答案是否定的。任务调度是自适应的;如果您的任务是调度程序确定为“长时间运行”的任务,则将根据需要将更多工作线程投入使用。为任务提供服务的线程池经过精心设计,可以动态响应环境。
主要问题不是线程用完(我的意思是,有可能您创建了这么多应用程序停止响应,但可能性很小),而是它抛出了整个想法通过窗外的异步 I/O 实现可扩展性。如果同步部分占主导地位,这可能比仅在线程上完成整个事情更糟糕。
Is there a more viable solution
总体思路是通过缓冲将反序列化与读取数据分离。读取一些字节,缓冲它们,确定您的缓冲区是否包含一个或多个完整的数据包,从缓冲区中删除这些数据包并反序列化它们(留下一些未反序列化的数据)。这要求您要么知道数据包的大小而不对其进行反序列化,要么您可以向反序列化逻辑提供一些字节,然后返回一个错误“需要更多数据”。除非反序列化器有副作用,否则这总是可以工作的。
The problem is that for example even just the size is not a simple numeric value, and even its size isn't a fixed amount of bytes. I could create an instance of the deserializer exclusively to read the size synchronously (just about 3-4 bytes usually), then read the payload asynchronously and then finally deserialize the latter but that adds quite some pressure on the GC, as well as making the code even more divided.
这里有两件事:
MemoryStream
,那么 GC 压力应该相当有限。包装数组段而不是复制数据。现在您需要担心的是 MemoryStream
对象本身,但您通常只会创建在第 1 代中清理的短期对象,所以不会很大。总体思路是这样的:
byte[] buffer;
int offset = 0;
int bytesRead = await Stream.ReadAsync(buffer, offset, buffer.Length - offset);
int bytesRemaining = bytesRead;
while (bytesRemaining != 0 && haveCompletishPacket(buffer, offset, bytesRemaining)) {
using (var memoryStream = new MemoryStream(buffer, offset, bytesRead)) {
int size = deserializer.Deserialize(memoryStream);
// deserialize as much as possible, if you run out of data,
// just reinit the deserializer and return
// if we got here we have a packet, produce it
offset += memoryStream.Position;
bytesRemaining -= memoryStream.Position;
}
}
确保正确维护缓冲区的细节很容易出错,所以我可能在上面的代码中弄错了。尽管如此,我希望这个想法很清楚。
显然,如果 haveCompletishPacket
可以在我们尝试反序列化器之前以 100% 的准确度告诉您缓冲区中是否有完整的数据包,那么这种方法效果最好(如果您的数据包总是成帧的话,这是可能的)具有恒定大小长度的类型),但只要我们读取足够的数据并且数据包不是太大,它就会“足够好”。
关于c# - NetworkStream ReadAsync 和 Read 同一个方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28663154/
我不确定我是否遗漏了什么或者 SslStream 中确实存在设计缺陷(可能还有其他可以包装内部流的流类)。 考虑这个伪代码: MyStream { Task ReadAsync() { ...
一段时间以来我一直在思考这个问题(并且知道这很愚蠢)。 我正在下载带有显示正常的 ProgressBar 的文件,但如何从 ReadAsync 流中获取数据进行保存? public static re
如果您不输入任何输入,为什么下面的代码永远不会完成,为什么即使在取消标记被取消后它仍然响应按下的键? // Set up a cancellation token var cancellationSo
我有以下代码(_ns 是一个 NetworkStream) await GetResponse(_ns); btnSend.Enabled = true; private async Task Get
我有一个 C# TcpClient 来异步读取数据。简化代码如下: public async Task StartReading(CancellationToken token) { // T
我以前使用过串行端口及其原始方法,如 BytesToRead、Read 和 Write。据说这些是不可靠的,我有很多忙等待我试图切换到它的异步方法。 我需要使用 2 个不同的超时时间从串口读取数据。第
我正在尝试使用 NetworkStream.ReadAsync() 来读取数据,但我找不到如何在调用后取消 ReadAsync()。对于背景,NetworkStream 由连接的 BluetoothC
当使用“SocketAsyncEventArgs”类和 ReadAsync 时,我应该将读取缓冲区放在哪里以及将发送缓冲区放在哪里?或者我只能一次阅读或发送而不是两者?我有点困惑。 最佳答案 我认为您
我正在尝试将下面的类转换为延迟返回文件。 public class ObservableFile2 : IObservable { private readonly IObservable s
试一试。使用单个按钮和按钮单击事件的以下代码设置新的 Windows 窗体应用程序: private async void button1_Click(object sender, EventArgs
当 NamedPipeServer 流从管道中读取任何数据时,它不会对 CancellationTokenSource.Cancel() 使用react 这是为什么? 如何限制我在服务器中等待来自客户
我正在使用 NetworkStream 和 TcpClient。 首先我设置我的 tcp 客户端: tcp = new TcpClient(AddressFamily.InterNetwork
NetworkStream.ReadAsync 什么时候任务完成?一旦接收到指定长度的数据? 如果是,它会返回 0 吗?然后 CancellationToken可以用作 ReadTimeout ,这是
在samples for the Cosmos DB SQL API , Database.ReadAsync() 有多种用途这似乎没有做任何有用的事情。该方法文档中的第二个注释并没有真正说明它可能用
在samples for the Cosmos DB SQL API , Database.ReadAsync() 有多种用途这似乎没有做任何有用的事情。该方法文档中的第二个注释并没有真正说明它可能用
我正在尝试在 .net 中使用 SerialPort 类。 我选择让我的服务保持异步,所以我在 SerialPort.BaseStream 上使用异步方法。 在我的异步方法中,我将一个 byte[]
鉴于以下情况: using System; using System.IO; using System.Threading; using System.Threading.Tasks; namespa
当调用 SQL Server 执行实际需要时间的操作时,SqlDataReader.ReadAsync() 会为我同步运行。有没有办法强制它异步运行,或者是我在 Task.Run() 中调用它的唯一选
我可以创建一个 MobileServiceClient 和 GetTable()至InsertAsync ,并查看如何将我的模型插入到 Azure 中的 Easy Table 表中。但是当我 Read
我正在尝试构建具有持久 TCP 连接的可扩展 服务器应用程序。我使用的序列化库是同步的,将其转换为APM会造成很大的开销(我已经测试过了)。 数据包的格式始终是数据包 ID 的一个字节,后跟几个 he
我是一名优秀的程序员,十分优秀!