简体   繁体   English

C#中具有异步TCP侦听器的多个客户端

[英]Multiple client with async TCP listener in C#

I have a problem with async TCP listener in C#. 我在C#中使用异步TCP侦听器有问题。 The main problem is I want to create async TCP listener in order to handle multiple connections. 主要问题是我想创建异步TCP侦听器以处理多个连接。 I have tons of requests from devices and webpages. 我收到了来自设备和网页的大量请求。 Also I have to use database to write specific information from these connections (read/write to/from SQL Server). 另外,我还必须使用数据库从这些连接中写入特定信息(对SQL Server进行读/写操作)。

The scenario of our task is this: One REST request will post from a webpage with a unique identifier to our Web API. 我们的任务场景是:一个REST请求将从具有唯一标识符的网页发布到我们的Web API。 Then our Web API makes a TCP connection to our listener, so we must halt this connection until we get another connection from a device with that unique identifier. 然后,我们的Web API与侦听器建立TCP连接,因此必须停止该连接,直到从具有该唯一标识符的设备获得另一个连接为止。 Then we send data which we got it before (webpage connection) to this connected device and again we must halt this connection too. 然后,我们将之前获得的数据(网页连接)发送到此连接的设备,同样,我们也必须停止此连接。 After processing this data in the device it will send us some other data again, and we must send this data to webpage which we halted it before. 在设备中处理完这些数据后,它将再次向我们发送其他一些数据,并且我们必须将这些数据发送到我们之前暂停的网页。

How can I find halted connection in our listener? 如何在监听器中找到暂停的连接?

Is there a better solution for us? 有没有更好的解决方案? (except using async TCP listener) (使用异步TCP侦听器除外)

Because of some customer reasons we are unable to use signalR or self-hosted Web API in C#. 由于某些客户原因,我们无法在C#中使用signalR或自托管的Web API。

Regards, Sara 问候,萨拉

'Halt' isn't the best word to describe what you need. “停止”并不是描述您所需要的最好的词。 If you need two-way communication with a web page over a REST request, you simply need to keep that request pending until the response is ready (not recommended, it could take really long and the connection could be dropped due to network conditions). 如果您需要通过REST请求与网页进行双向通信,则只需将该请求保持待处理状态,直到响应就绪为止(不建议这样做,这可能会花费很长时间,并且由于网络状况可能会断开连接)。 Do reconsider your choice of avoiding SignalR. 请重新考虑避免使用SignalR的选择。 However, if need be, you can keep the request thread waiting. 但是,如果需要,您可以使请求线程保持等待状态。 To do that, you'd need either a TaskCompletionSource (if you're processing the request within a Task) or a synchronization primitive such as a ManualResetEvent . 为此,您需要TaskCompletionSource (如果正在处理Task中的请求)或同步原语(例如ManualResetEvent I can't really give you more details without knowing the conditions your code will run under. 在不知道您的代码将在何种条件下运行的情况下,我无法为您提供更多详细信息。

On the device side of things, again you need two way communication. 在设备方面,同样需要双向通信。 You could implement this in one of two ways: 您可以通过以下两种方式之一来实现此目的:

  1. The device opens a TCP connection and keeps it open. 设备打开TCP连接并保持打开状态。 The server receives the ID, and then sends the data back over the connection. 服务器接收ID,然后通过连接将数据发送回去。 The device then processes this data in some way and sends its response back to the server over the same connection and terminates the connection. 然后,设备以某种方式处理此数据,并通过相同的连接将其响应发送回服务器,并终止连接。

  2. The device makes the equivalent of a REST GET request to the server to grab the data from the web page. 该设备向服务器发出REST GET请求的等效内容,以从网页中获取数据。 It then processes the data and makes the equivalent of a POST request to send its own data back to the server. 然后,它处理数据并进行POST请求,以将其自身的数据发送回服务器。

After this is done, you still have the connection from the web page waiting for a response. 完成此操作后,您仍然可以连接来自网页的连接,以等待响应。 Simply let it know the transaction has completed, using TaskCompletionSource.SetResult or ManualResetEvent.Signal . 使用TaskCompletionSource.SetResultManualResetEvent.Signal使其简单地知道事务已完成。 The server can then write whatever data it needs in the response to the web page's request and close that connection too. 然后,服务器可以在响应网页请求时写入所需的任何数据,并也关闭该连接。

Also note that there is no such thing as a halted connection. 另请注意,没有停止连接之类的东西。 You just intentionally delay writing a response. 您只是故意拖延写回复。


EDIT: You can't really hold the connection (not with the normal execution flow of most web servers at least), but you can stop the thread processing that connection. 编辑:您不能真正保持连接(至少不与大多数Web服务器的正常执行流程保持连接),但是您可以停止处理该连接的线程。 This is a heavily simplified (and completely inappropriate for any real system) example: 这是一个大大简化的示例(对于任何实际系统都是完全不合适的)示例:

// ConnectionManager.cs
public static Dictionary<Guid, TaskCompletionSource<DataToSendToWebPage>> connectionTCSs;

// WebPageRequestHandler.cs
async Task HandleClientRequest() {
    // do some stuff
    var tcs = new TaskCompletionSource<DataToSendToWebPage>();
    ConnectionManager.connectionTCSs[deviceID] = tcs;
    var result = await tcs.Task; // This is where you wait for the other flow to complete
    // Write response to connection
}

// DeviceRequestHandler.cs
void HandleRequest() {
    // do stuff
    ConnectionManager.connectionTCSs[clientID].SetResult(result);
}

The general idea is that you keep the thread (or task) processing the web page request waiting, and then signal it to continue from the other thread when the device's connection is handled and data is received. 通常的想法是让处理网页请求的线程(或任务)等待,然后在处理设备的连接并接收到数据时发信号通知另一个线程继续执行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM