【发布时间】:2019-10-16 02:51:34
【问题描述】:
我正在使用 .NET 框架来创建一个服务器,它监听本地主机上的两个端口。这是一个简单的控制台应用程序。
当我继续连接到其中一个端口时它可以工作,但是在我第一个连接后,另一个没有响应。第一个还活着。
这是我的代码:
static void Main(string[] args)
{
IPAddress hostIP = Dns.GetHostAddresses("127.0.0.1")[0];
List<TcpListener> listeners = new List<TcpListener>()
{
new TcpListener(hostIP, 6060),
new TcpListener(hostIP, 6061)
};
foreach (TcpListener listener in listeners)
{
listener.Start();
}
try
{
while (true)
{
Socket socket = AcceptAnyConnection(listeners).Result;
NetworkStream stream = new NetworkStream(socket);
byte[] bytes = Encoding.UTF8.GetBytes(DateTime.Now.ToString());
stream.Write(bytes, 0, bytes.Length);
//stream.Close();
socket.Close();
}
}
finally
{
foreach (TcpListener listener in listeners)
{
listener.Stop();
}
}
}
private static async Task<Socket> AcceptAnyConnection(List<TcpListener> listeners)
{
List<Task<Socket>> tasks = new List<Task<Socket>>();
foreach (TcpListener listener in listeners)
{
tasks.Add(AcceptConnection(listener));
}
Task<Socket> completedTask = await Task.WhenAny(tasks);
return await completedTask;
}
private static async Task<Socket> AcceptConnection(TcpListener listener)
{
Socket socket = await listener.AcceptSocketAsync();
return socket;
}
如果我连接到另一个端口,则等待 Task.WhenAny() 阻塞。
我一定是做错了什么,但我不确定是什么。
顺便说一句,我确实尝试过使用 .NET Core 控制台应用程序,它工作正常。
谢谢
【问题讨论】:
-
这很复杂,但如果你不使用
.Result而使用await,它会起作用……让你的主函数成为异步任务。 -
一个问题是,每当一个监听器获得一个新的连接时,你都会在所有监听器上调用
AcceptSocketAsync(并丢弃你上次调用它时之前未完成的任务)。相反,您可能希望维护一个List<Task<Socket>>,并且每次其中一个完成时,将其从列表中删除,在任务完成的侦听器上调用AcceptSocketAsync,并将新任务放入列表中 -
Archie,虽然以上两个答案都是正确的,但我建议您在这里深入研究事件模式,您可以让每个侦听器工作到一个单独的线程中,并且每当您找到连接或消息时都会触发一个事件到应用程序的另一层,您不会遇到这样的问题
-
你绝对不能在任何你不知道要完成的任务上使用
Result;这会使您的异步工作流变成同步工作流,然后可能会死锁!
标签: c# .net server async-await