每个接受多个连接时如何监听多个TCP端口
How to listen to multiple TCP ports when each one accepts multiple connections
我需要使用 TcpListener 监听多个端口,我需要 TcpListener 接受多个连接并单独处理每个连接,这是我编写的代码,但如您所见,它只监听第一个端口然后转到 while(true)
并监听到达该端口的所有连接。知道我怎样才能为多个连接监听多个端口吗?
private static async Task TcpServerAsync()
{
try
{
IPAddress ip;
if (!IPAddress.TryParse(ConfigurationManager.AppSettings["ipAddress"], out ip))
{
Console.WriteLine("Failed to get IP address, service will listen for client activity on all network interfaces.");
ip = IPAddress.Any;
}
foreach (Ports port in Ports.GetValues(typeof(Ports)))
{
Log.Info("Starting listener...");
var tcpListener = new TcpListener(ip, (int)port);
tcpListener.Start();
Log.Info("Listening...");
var startTimeSpan = TimeSpan.Zero;
var periodTimeSpan = TimeSpan.FromSeconds(10000000);
while (true)
{
TcpClient client = await tcpListener.AcceptTcpClientAsync();
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, 1);
HandleByPortNumber(client, (int)port);
}
}
}
catch (Exception ex)
{
Log.Info("Error Happened : " + ex + ex.InnerException);
}
}
和
public static void HandleByPortNumber(TcpClient client , int portNumber)
{
switch (portNumber)
{
case (int)Ports.Teltonica:
var cw = new Teltonika.TcpClientService(client);
ThreadPool.UnsafeQueueUserWorkItem(x => ( (Teltonika.TcpClientService)x).Run(), cw);
break;
case (int)Ports.OBDTracker:
break;
}
}
和
public enum Ports
{
Teltonica = 3000,
OBDTracker = 3001
}
这是一个删除了额外功能(日志记录等)的实现。测试和工作。这里要解决的问题是如何从 Task 映射回它的侦听器和端口号。显然,我的端口号列表对您不起作用,但除此之外应该可以。您还希望将 Tuple<> 替换为自定义 class,以获得更好的可读性。
IDictionary<Task<TcpClient>, Tuple<int, TcpListener>> tcpListeners = new Dictionary<Task<TcpClient>, Tuple<int, TcpListener>>();
foreach (var port in Enumerable.Range(20000, 5))
{
var tcpListener = new TcpListener(IPAddress.Any, port);
tcpListener.Start();
var task = tcpListener.AcceptTcpClientAsync();
var tcpListenerPortPair = new Tuple<int, TcpListener>(port, tcpListener);
tcpListeners.Add(task, tcpListenerPortPair);
}
Task<TcpClient> tcpClientTask;
while ((tcpClientTask = await Task.WhenAny(tcpListeners.Keys)) != null)
{
var tcpListenerPortPair = tcpListeners[tcpClientTask];
var port = tcpListenerPortPair.Item1;
var tcpListener = tcpListenerPortPair.Item2;
tcpListeners.Remove(tcpClientTask);
// This needs to be async. What to do with its Task?
// It cannot be awaited here.
var handlerTask = HandleByPortNumber(tcpClientTask.Result, port);
var task = tcpListener.AcceptTcpClientAsync();
tcpListeners.Add(task, tcpListenerPortPair);
}
我需要使用 TcpListener 监听多个端口,我需要 TcpListener 接受多个连接并单独处理每个连接,这是我编写的代码,但如您所见,它只监听第一个端口然后转到 while(true)
并监听到达该端口的所有连接。知道我怎样才能为多个连接监听多个端口吗?
private static async Task TcpServerAsync()
{
try
{
IPAddress ip;
if (!IPAddress.TryParse(ConfigurationManager.AppSettings["ipAddress"], out ip))
{
Console.WriteLine("Failed to get IP address, service will listen for client activity on all network interfaces.");
ip = IPAddress.Any;
}
foreach (Ports port in Ports.GetValues(typeof(Ports)))
{
Log.Info("Starting listener...");
var tcpListener = new TcpListener(ip, (int)port);
tcpListener.Start();
Log.Info("Listening...");
var startTimeSpan = TimeSpan.Zero;
var periodTimeSpan = TimeSpan.FromSeconds(10000000);
while (true)
{
TcpClient client = await tcpListener.AcceptTcpClientAsync();
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, 1);
HandleByPortNumber(client, (int)port);
}
}
}
catch (Exception ex)
{
Log.Info("Error Happened : " + ex + ex.InnerException);
}
}
和
public static void HandleByPortNumber(TcpClient client , int portNumber)
{
switch (portNumber)
{
case (int)Ports.Teltonica:
var cw = new Teltonika.TcpClientService(client);
ThreadPool.UnsafeQueueUserWorkItem(x => ( (Teltonika.TcpClientService)x).Run(), cw);
break;
case (int)Ports.OBDTracker:
break;
}
}
和
public enum Ports
{
Teltonica = 3000,
OBDTracker = 3001
}
这是一个删除了额外功能(日志记录等)的实现。测试和工作。这里要解决的问题是如何从 Task 映射回它的侦听器和端口号。显然,我的端口号列表对您不起作用,但除此之外应该可以。您还希望将 Tuple<> 替换为自定义 class,以获得更好的可读性。
IDictionary<Task<TcpClient>, Tuple<int, TcpListener>> tcpListeners = new Dictionary<Task<TcpClient>, Tuple<int, TcpListener>>();
foreach (var port in Enumerable.Range(20000, 5))
{
var tcpListener = new TcpListener(IPAddress.Any, port);
tcpListener.Start();
var task = tcpListener.AcceptTcpClientAsync();
var tcpListenerPortPair = new Tuple<int, TcpListener>(port, tcpListener);
tcpListeners.Add(task, tcpListenerPortPair);
}
Task<TcpClient> tcpClientTask;
while ((tcpClientTask = await Task.WhenAny(tcpListeners.Keys)) != null)
{
var tcpListenerPortPair = tcpListeners[tcpClientTask];
var port = tcpListenerPortPair.Item1;
var tcpListener = tcpListenerPortPair.Item2;
tcpListeners.Remove(tcpClientTask);
// This needs to be async. What to do with its Task?
// It cannot be awaited here.
var handlerTask = HandleByPortNumber(tcpClientTask.Result, port);
var task = tcpListener.AcceptTcpClientAsync();
tcpListeners.Add(task, tcpListenerPortPair);
}