问题标签 [socketasynceventargs]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
595 浏览

.net - SocketAsyncEventArgs 片段顺序

我在使用 SocketAsyncEventArgs 接收套接字数据包排序时遇到问题。我的问题的症结在于,当客户端向服务器发送数据包时,服务器将以非标准大小的片段接收数据包,并且它们将按随机顺序进行处理。这显然意味着数据包无法被我的应用程序解码,从而搞砸了整个对话。

例如,客户端将使用 Socket.NetworkStream.Write() 方法发送一个完整的数据包:

服务器使用 SocketAsyncEventArgs 将在两个单独的数据包上接收异步回调,但将首先处理数据包的最后一个块:

这不会发生在所有数据包上,我无法根据数据包大小或时间准确地重现它。我实现了一个发送/确认通信协议,以便客户端不会发送另一个数据包,直到服务器确认最后一个数据包已成功接收,所以它不可能是我超载的服务器。

最令人沮丧的部分是服务器上的 Socket.Available始终为零,根据文档,这意味着没有任何内容可供读取

可用为零时,SocketEventArgs.Count 似乎没有提供任何价值,并且偏移量与接收缓冲区有关,而不是基于实际数据流的位置我不确定如何将这些片段放入命令。

我猜这个问题是数据包第一部分的异步回调被第二个回调抢占了,该回调完全处理然后返回到第一部分。问题是我无法同步锁定整个回调(希望 .NET 有像 Java 这样的同步函数)。即使我这样做了,这似乎首先会否定异步回调的好处。

我做错了什么导致这些顺序错误,或者我可以做些什么来正确处理它们?

0 投票
1 回答
4425 浏览

c# - TcpListener 与 SocketAsyncEventArgs

是否有正当理由不TcpListener用于实现高性能/高吞吐量TCP服务器而不是SocketAsyncEventArgs

我已经实现了这个高性能/高吞吐量的 TCP 服务器SocketAsyncEventArgs,使用一个大的预先分配的byte数组和SocketAsyncEventArgs用于接受和接收的池来处理那些固定的缓冲区,使用一些低级的东西和闪亮的智能放在一起带有一些 TPL 数据流和一些 Rx 的代码,它工作得很好;几乎是这方面的教科书——实际上我已经从别人的代码中学到了超过 80% 的这些东西。

但是也存在一些问题和担忧:

  1. 复杂性:我不能将此服务器的任何类型的修改委托给团队的其他成员。这将我限制在这类任务中,我无法对其他项目的其他部分给予足够的关注。
  2. 内存使用(固定byte数组):SocketAsyncEventArgs需要预先分配使用池。因此,为了处理 100000 个并发连接(更糟糕的情况,即使在不同的端口上),一大堆 RAM 无用地悬停在那里;预先分配(即使这些条件只是在某些时候满足,服务器应该能够每天处理 1 或 2 个这样的峰值)。
  3. TcpListener实际上效果很好:我实际上已经进行TcpListener了测试(使用了一些技巧,例如AcceptTcpClient在专用线程上使用,而不是 async 版本,然后将接受的连接发送到 a 而不是就地ConcurrentQueue创建s 等)和最新版本的 . TaskNET,它工作得非常好,几乎和 .NET 一样好SocketAsyncEventArgs,没有数据丢失和低内存占用,这有助于在服务器上不浪费太多 RAM 并且不需要预先分配。

那么,为什么我看不到TcpListener在任何地方被使用并且每个人(包括我自己)都在使用SocketAsyncEventArgs?我错过了什么吗?

0 投票
3 回答
481 浏览

.net - SocketAsyncEventArgs“pooled byte[]”样式是否有助于减少内存需求?

我看不出池化的 SocketAsyncEventArgs样式如何帮助我减少服务于许多并发连接的服务器的内存消耗。

是的,它提供了 MS 的 Begin/End 样式的替代方案,上述 MSDN 页面描述为需要a System.IAsyncResult object be allocated for each asynchronous socket operation.

最初的研究让我相信,出于某种原因,它最多只允许我分配少数字节数组,并在我的数千个并发连接的客户端之间共享它们。

但似乎如果我想在数千个客户端连接上等待数据,我必须调用ReceiveAsync数千次,每次都提供一个不同的字节数组(包装在 SocketAsyncEventArgs 中),然后这数千个数组将坐在那里直到客户端决定发送的时间,很可能是 10 秒。

因此,除非我在客户端发送数据时调用 ReceiveAsync(或者在那之后,依赖于一些网络堆栈缓冲区?)——这是由客户端自行决定且服务器无法预测的,否则我很不走运,字节数组将坐在那里,无所事事地等待客户动他的屁股。

我希望用一个字节数组(或者每个侦听线程一个数组,如果并行化有意义的话)来监听那些数千个连接,并且一旦这些连接中的任何一个发送了一些东西(这确实必须进入一些网络堆栈缓冲区首先无论如何),它将被复制到该数组中,我的侦听器被调用,一旦侦听器完成,该数组就可以被重用。

Socket.*Async() 方法确实不可能吗?

.net 的套接字库有可能实现这样的事情吗?

0 投票
0 回答
75 浏览

.net - 在多个 SocketAsyncEventArgs 之间共享发送字节 [] 缓冲区

在我总是向许多客户端发送相同数据的情况下,即在我应该(并且将来会)可能切换到使用(例如 PGM)多播的情况下,使用相同的数组是否是线程安全byte[]的多个实例并将它们通过并发发送SocketAsyncEventArgs到多个套接字?SendAsync

毕竟,SendAsync 应该从缓冲区中读取,因此共享实例应该不是问题。我想以后要启用该缓冲区的重用,我必须进行引用计数,并且可能还有其他问题需要解决,但我的问题首先是关于线程安全的。

0 投票
1 回答
1941 浏览

c# - How to implement IDisposable interface in a class inherited from SocketAsyncEventArgs

I work on a huge project in C# .NET 4.0. There is a custom class inherited from System.Net.Sockets.SocketAsyncEventArgs class. Something like the following:

So, I wanted to move the content of CleanUp() method to Dispose(bool) method.

As first, I checked the source code of the base class - SocketAsyncEventArgs (using Go To Definition so that I saw metadata as source). I found out, this class implements IDisposable interface. Nice, I just need to override the Dispose(bool) method, don't I? (See IDisposable Interface on MSDN, the "IDisposable and the inheritance hierarchy" section, for more details). Nothing new for me... Unfortunately, the SocketAsyncEventArgs class is implemented as following:

That means, there is no way how to override Dispose(bool) method, as it's implemented as private instead of protected... What is the reason for this?

Next, I read about SocketAsyncEventArgs.Dispose() method on MSDN. The funny thing is that, it contains the following section:

Notes to Inheritors

Dispose can be called multiple times by other objects. When overriding Dispose(Boolean), be careful not to reference objects that have been previously disposed of in an earlier call to Dispose. For more information about how to implement Dispose(Boolean), see Implementing a Dispose Method.

Wait... what?

When overriding Dispose(Boolean), ...

How am I supposed to override Dispose(Boolean)?

What is the recommended way to implement IDisposable interface in this case?

0 投票
0 回答
611 浏览

c# - 使用 SocketAsyncEventArgs 将数据推送到 C# TCP 客户端

我按照链接创建了一个异步 TCP 服务器。但是,所有示例仅涵盖发送数据作为对接收的响应。我的问题是如何将数据推送到某个 TCP 客户端。

假设需要将一个字节 [] 发送/推送到客户端 ID 1。如何使用 SocketAsyncEventArgs 架构来实现这一点?

我知道我必须保留活动连接和客户端 ID 的列表。为了推送数据,这个列表应该是什么样子?

0 投票
1 回答
191 浏览

c# - 双工服务器环境中的 SocketAsyncEventArgs?

我正在学习使用 MSDN 教程使用 SocketAsyncEventArgs 的东西。我只是想知道一些事情,即如何实现具有全双工功能的服务器。

目前,MSDN 示例教您创建一个服务器,该服务器首先侦听,然后在收到某些内容时将其发回。只有这样服务器才会再次开始监听。

我想出自己的解决方案的问题是该SocketAsyncEventArgs对象只有一个事件,Completed即为发送和接收而触发。它没有其他事件。

我在一些翻译得很糟糕的网站上读到

必须使用两个SocketAsyncEventArgs,一个接收一个发。

-未知

我发现这个所谓的“增强”套接字实现有少量令人不安的信息......

这是我的一些代码,所以你可以看到我在做什么。

谢谢!

0 投票
0 回答
301 浏览

c# - 当两个端点都执行 Socket.SendAsync 时死锁

所以我编写了这个客户端/服务器套接字应用程序,它使用 SocketAsyncEventArgs“方法”来执行异步套接字。

使用我用于许多其他应用程序的同一个库,我现在第一次遇到了我从未预料到的情况。

我们的新客户端/服务器应用程序启动后,开始双向发送大量数据。

当在单元测试中使用模拟对象(无延迟)来模拟正常的套接字操作时,一切正常。

但是在使用真实套接字的实际情况中,我们会遇到一种死锁,其中两个端点都卡在 Socket.SendAsync() 操作中(是的,它返回 true,没有同步处理)

我的想法是双方的接收缓冲区已满,并且 tcp 堆栈不再确认任何帧。(连接到 127.0.0.1)

所以我将接收缓冲区设置为发送缓冲区的两倍,但不幸的是,由于我们的“协议”的性质以及我们如何确定发送或接收,这并不是那么简单。

我现在必须重新考虑确定何时开始发送和何时开始接收的方法。

一个复杂的因素是,这个连接的目的是在这个套接字连接上多路复用多个双向通用通信通道。这意味着没有预先确定的通信顺序,所有通道都可能有自己的协议。

当然,还有 tls 启动、握手和身份验证,这些都运行良好,但是当连接开始运行,并且通道开始自己的通信时,唯一确定的是接收到的数据具有大小和通道号作为标头。

每次操作后,我检查接收缓冲区中是否有任何等待数据,或者通过检查 Socket.Available。

这与测量自上次发送操作以来接收到的数据量以及传输缓冲区的满载情况相结合,我决定接收更多或开始发送,或者什么都不做,并在 xx 毫秒内再次轮询。

我现在意识到这是错误的。

我是否试图完成仅使用一个套接字连接根本不可能完成的事情?

任何人都试图完成类似的事情,或者知道一种完成不会引入这些奇怪锁定的安全方式的好方法。

谢谢,西奥。

0 投票
1 回答
193 浏览

garbage-collection - BeginReceive/SocketAsyncEventArgs ArraySegments 列表

传递to /列表背后的原因是什么?ArraySegment<byte>Socket.BeginReceiveSocketAsyncEventArgs

Socket.BeginReceive构造函数的 MSDN甚至没有正确描述第一个参数):

参数:
buffers
类型:类型System.Collections.Generic.IList<ArraySegment<Byte>>
数组Byte,是接收数据的存储位置。
...

我认为主要的想法是在大对象堆上分配一个大缓冲区,然后将这个缓冲区的一部分传递给Socket.BeginReceive,以避免将小对象钉在堆周围并弄乱 GC 的工作。

但是为什么我要向这些方法传递几个段呢?如果是SocketAsyncEventArgs,似乎会使这些对象的池化复杂化,我看不出这背后的原因。

0 投票
1 回答
270 浏览

c# - 带有二进制/字节 [] 流的 SocketAsyncEventArgs

我是 C# 和套接字的新手,所以如果我的问题不合时宜,我深表歉意。我开始使用此链接中的示例构建套接字接口: https ://code.msdn.microsoft.com/High-Performance-NET-69c2df2f

我希望能够通过套接字传输二进制文件,所以我做了一个假设(可能是错误的),我不应该使用StringBuilder. 我将原始代码更改OSUserToken为使用MemoryStreamand BinaryWriter(注释掉原始代码)。

在代码的其他地方(来自上面的链接),SocketAsyncEventArgsSetBuffer(new Byte[_bufferSize], 0, _bufferSize);. 我担心这不会很好地适应我的MemoryStreamBinaryWriter但它似乎工作。

当我运行它时,它似乎可以正常工作。即使我设置protected const int DEFAULT_BUFFER_SIZE = 1它也会接受> 1字节的流:

我的问题是:

  1. 我是对的,StringBuilder这不适用于二进制文件,我应该使用MemoryStreamandBinaryWriter吗?
  2. SocketAsyncEventArgs如果在程序的其他地方用初始化,我是否需要关注缓冲区溢出SetBuffer(new Byte[_bufferSize], 0, _bufferSize);
  3. 如果我必须遵守缓冲区大小限制,我是否需要对发送数据的客户端设置相同的缓冲区限制?