托盘应用程序中的TCP侦听器,不能为同一机器上的多个用户运行
本文关键字:机器 用户 运行 不能 应用程序 TCP 侦听器 | 更新日期: 2023-09-27 18:04:15
我将这样开始:我知道您只能有一个TcpListener侦听任何给定的端口,我正在试图找到一种方法来解决这个限制。
我正在尝试在同一台机器上构建一个支持另一个应用程序的应用程序。另一个我无法控制的应用程序在打开或关闭研究时,会在TCP端口上发出信号。
为了接受这个TCP信号,我建立了一个Windows托盘应用程序来监听该端口,接受信号,然后处理传输到它的数据。管理此侦听器的代码块如下所示:
private TcpListener _tcpListener;
private Thread _listenerThread;
#region TCP Connection
public void StartListener()
{
if (_listenerThread != null)
StopListener();
_listenerThread = new Thread(RunListener);
_listenerThread.Start();
}
private void RunListener()
{
_tcpListener = new TcpListener(IPAddress.Any, this.TcpListenerPort);
_tcpListener.Start();
while (true)
{
Console.WriteLine(string.Format("Listening for connections on port {0}", this.TcpListenerPort));
try
{
TcpClient client = _tcpListener.AcceptTcpClient();
ThreadPool.QueueUserWorkItem(ProcessClient, client);
}
catch (SocketException ex)
{
// This occurs when we close the parent thread that runs the TcpListener because
// the TcpListener call to AcceptTcpClient is a blocking call.
}
catch (Exception ex)
{
Console.WriteLine(string.Format("Exception trying to AcceptTcpClient: {0}", ex.Message));
}
}
}
private void StopListener()
{
if (_tcpListener != null)
_tcpListener.Stop();
if (_listenerThread != null)
_listenerThread.Abort();
}
如您所见,这是非常简单和直接的。我设置一个线程来容纳Listener,然后等待信号通过,然后对它发送给我的数据执行一些操作。所有这些都运行良好。
问题来自于:这个托盘应用程序被设置为当用户登录到机器时运行。但是,由于TCP侦听器的"每个端口一个侦听器"规则,如果有多个用户同时登录到机器上(通过VPN或通过"切换"而不是注销),则会尝试启动该应用程序的第二个实例。并立即崩溃,因为它试图侦听已经被侦听的端口。
我不能改变其他程序发送信息给我的方式,我不能强迫Windows用户在切换到一个新用户之前正确地注销。我也不能把这些零件装到别的机器上。然而,这个托盘应用程序需要对每个用户可用。
我已经想不出如何解决这个问题了,任何建议都将非常有帮助。
具体来说,我试图找到一种方法来劫持托管TcpListener的现有线程,在同一台机器上同时选择多个Windows帐户使用它。当然,我也不会拒绝一个比我现有的更好的主意。
编辑:我考虑过将其作为服务运行,但是侦听器接收数据的结果之一是托盘应用程序启动web浏览器,并且它有一个用于配置其设置的用户界面。
由于我的代表关系,我还不能发表评论,所以这个答案不是一个真正的答案,但是你的设计有问题。因此,您有4个用户登录到这台机器,因此有4个用户设置UI实例等。当任何/所有4个UI应用程序接收到来自发送应用程序的通信时,如果有,哪个应该响应它?
都是4吗?如果都是4,那么使用服务"监听"的建议是正确的,1个服务监听1个端口。当它得到一些东西时,它可以与UI应用程序通信。让他们在启动和设置自己的侦听端口时与服务交谈,以便服务可以跟踪谁仍在侦听并命令该应用程序打开网页,因此所有4个主动侦听的UI应用程序都会打开网页。
如果只有1个UI应该响应,那么你需要确定规则来选择哪一个,那么我仍然认为服务将是正确的方式,服务可以根据定义的规则确定4个中的哪一个,应该得到打开网页的命令。
最后,我还是不会这样做,在用户没有参与的情况下打开应用程序可能会导致错误的数据,例如,他们在键盘上打字,甚至没有看一下显示器,突然意识到他们在最后4次输入按键中输入了错误的表单,以为他们在输入电子邮件。你确定任务栏通知不是更好的主意吗?
这与端口的概念相反。最好的情况是程序的所有副本都能并行地接收和处理数据。
也许一个更好的方向是让托盘应用程序放弃端口时,会话被锁定?参见如何检测Windows被锁定?