托盘应用程序中的TCP侦听器无法在同一台计算机上运行多个用户

时间:2016-08-25 19:35:38

标签: c# multithreading tcp tcplistener

我打开这个:我知道你只能有一个TcpListener监听任何给定的端口,我试图找到解决这个限制的方法。

我正在尝试构建一个支持同一台机器上的另一个应用程序的应用程序。另一个我无法控制的应用程序在打开或关闭研究时在TCP端口上发出信号。

为了接受这个TCP信号,我构建了一个Windows托盘应用程序,它监听该端口,接受信号,然后处理传输给它的数据。管理此Listener的代码块如下所示......

    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();
    }

如您所见,这非常简单直接。我调整一个线程来保持监听器,然后等待信号通过,然后对它发送给我的数据做一些事情。所有这一切都很好。

问题来自于:此托盘应用程序设置为在用户登录计算机时运行。但是,由于每个端口的一个监听器' TCP侦听器的规则,如果多个用户一次登录到计算机(通过VPN或通过切换而不是注销),则此应用程序的第二个实例将尝试启动。并迅速崩溃,因为它试图侦听已经被收听的端口。

我无法更改其他程序向我发送信息的方式,我无法强制Windows用户在切换到新用户之前正确注销。我也无法将这些部件重新安置到不同的机器上。但是,此托盘应用程序需要供每个用户使用。

我已经完成了如何解决这个问题的想法,任何输入都会非常有用。

具体来说,我试图找到一种方法来劫持托管TcpListener的现有线程,并在同一台机器上同时将其添加到多个Windows帐户中使用。当然,我肯定不会拒绝比我拥有的更好的想法。

编辑:我曾考虑将其作为服务运行,但是监听器收到的数据的一个结果是托盘应用程序启动了一个Web浏览器,它有一个用户界面来配置其设置。

2 个答案:

答案 0 :(得分:1)

由于我的代表,我还不能发表评论,所以这个答案并不是真正的答案,但你的设计有问题。因此,您有4个用户登录到此计算机,因此用户设置的用户界面的4个实例等。当任何/所有4个UI应用程序从发送应用程序接收通信时,如果有任何响应它的话?

全部是4吗?如果它全部是4,那么建议使用服务来"听"是正确的,1服务侦听1端口。当它获得某些东西时,它就可以与UI应用程序进行通信。让他们在启动和设置他们自己的监听端口时与服务对话,以便服务可以跟踪谁仍在监听并命令该应用程序打开网页,因此所有4个主动监听的UI应用程序将打开网页。

如果只有1个用户界面应该响应,那么你需要确定选择哪个规则,然后我仍然认为服务是正确的方式,服务可以根据定义的规则确定4中的哪一个,应该获得打开网页的命令。

最后,我仍然不会这样做,在没有他们参与的情况下打开用户的应用程序会导致数据不良,即他们正在键盘上输入,甚至没有看到显示器,突然间意识到他们在最后4次输入印刷机时输入了错误的表格,认为他们正在输入一封电子邮件。您确定任务栏通知不是更好的主意吗?您可以根据需要将它们设为侵入式。

答案 1 :(得分:0)

这与港口的想法相反。您可能希望的最好的是程序的所有副本并行接收和处理数据。

或许更好的方向是让托盘应用程序在会话锁定时放弃端口?见How to detect Windows is locked?