因此,我在正在监听端口9096的控制台应用程序中有一个TcpClient。我希望客户端能够处理多个连接(同时或不同时)。我也不想使用线程。我想使用异步/等待。在某些事件中,我还需要能够正常关闭应用程序,请注意不要丢失任何数据。所以我需要一个取消令牌。我的代码大部分都能正常工作,但是有两个问题。
首先,当应用开始监听并发送数据时;只要发件人使用与应用程序相同的初始连接,一切都可以正常工作。一旦建立了新的连接(或我想知道的套接字?在术语上不清楚),应用程序就不会处理新数据。
第二,当向应用程序发出终止信号并且令牌被取消时,应用程序不会关闭。我没有任何例外,也无法弄清楚自己在做什么错。
我四处张望,找不到使用带有取消令牌的async / await的TcpClient的示例。我也找不到一个示例,说明我能够使用多个线程或其他复杂的设计来正确处理多个连接。我希望设计尽可能简单,代码尽可能少,同时又能满足我的要求。如果使用线程是唯一的方法,那么我会做,但是我已经很接近正确了,我觉得我只是缺少了一点东西。
我竭尽全力试图解决这个问题,并耗尽了我所有的想法。
编辑:我按照以下建议将AcceptTcpClientAsync
移到了循环中,它没有任何改变。应用程序的功能与以前相同。
Program.cs
class Program
{
private static List<Task> _listeners = new List<Task>();
private static readonly CancellationTokenSource cancelSource = new CancellationTokenSource();
static void Main(string[] args)
{
Console.TreatControlCAsInput = false;
Console.CancelKeyPress += (o, e) => {
Console.WriteLine("Shutting down.");
cancelSource.Cancel();
};
Console.WriteLine("Started, press ctrl + c to terminate.");
_listeners.Add(Listen(cancelSource.Token));
cancelSource.Token.WaitHandle.WaitOne();
Task.WaitAll(_listeners.ToArray(), cancelSource.Token);
}
}
听
public async Task Listen(CancellationToken token){
var listener = new TcpListener(IPAddress.Parse("0.0.0.0"), 9096);
listener.Start();
Console.WriteLine("Listening on port 9096");
while (!token.IsCancellationRequested) {
// Also tried putting AcceptTcpClientAsync here.
await Task.Run(async () => {
var client = await listener.AcceptTcpClientAsync();
using (var stream = client.GetStream())
using (var streamReader = new StreamReader(stream, Encoding.UTF8))
using (var streamWriter = new StreamWriter(stream, Encoding.UTF8)) {
while (!token.IsCancellationRequested) {
// DO WORK WITH DATA RECEIVED
vat data = await streamReader.ReadAsync();
await streamWriter.WriteLineAsync("Request received.");
}
}
});
}
Console.WriteLine("Stopped Accepting Requests.");
listener.Server.Close();
listener.Stop();
}
答案 0 :(得分:0)
这实际上是按照您设计的方式工作的,但是您只能建立一个连接。我不会为您编写完整的套接字实现(因为这可能会相当深入)。但是,对于您的主要问题,您需要将AcceptTcpClientAsync
放入循环中,否则将无法获得更多连接
var cancellation = new CancellationTokenSource();
...
var listener = new TcpListener(...);
listener.Start();
try
{
while (!token.IsCancellationRequested)
{
var client = await listener.AcceptTcpClientAsync()
...
}
}
finally
{
listener.Stop();
}
// somewhere in another thread
cancellation.Cancel();
更新
我尝试过,并且没有任何变化。还是不接 连接在第一个之后。
await ...
while (!token.IsCancellationRequested) {
// DO WORK WITH DATA RECEIVED
很明显,AcceptTcpClientAsync
永远不会再被调用,因为您正在等待任务。这种方法可以接受客户端,如果您不能调用它,就不会再获得任何客户端。
您不能在这里阻止,这是您在做什么。请查看一些套接字服务器示例,以更好地了解如何编写侦听器