立即停止所有SSH连接

时间:2015-07-23 06:34:38

标签: c# linux multithreading ssh backgroundworker

我正在开发一个程序,该程序应该与远程Linux服务器建立“n”许多SSH连接,并在每个连接上运行耗时的命令。 “耗时的操作”基本上是运行一个脚本来设置Wireshark并监听流量。

为此,我将SharpSSH库用于C#,将许多BackgroundWorkers用作线程。同样为简单起见,下面的代码有n = 2个BGW线程和SSH连接。

代码:

    // runs when start is pressed
    private void startButton_Click_1(object sender, EventArgs e)
    {
        sb = new StringBuilder();
        DateTime timeNow = DateTime.Now;
        clickTime = timeNow.ToString("yyyyMMddhhmmssfff"); // store the exact time of the click
        bw = bwArray[0];
        int index = 0; // ignore these 2 constants

        foreach (BackgroundWorker bgw in bwArray)
        {
            if (bgw.IsBusy != true)
            {
                bgw.RunWorkerAsync(); 
                // runWorkerAsync for every BackgroundWorker in the array
                //index++;
            }
        }

    }
    // runWorkerAsync leads the BGWorker to this function
    private void bw_doWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;

        if (worker.CancellationPending == true)
        {
            e.Cancel = true;
        }
        else
        {
            // let the UI know of button changes
            int p = 0;
            object param = "something"; // use this to pass any additional parameter back to the UI
            worker.ReportProgress(p, param);
            // UI notifying part ends here

            // for the simplex case
            if (numberOfConnections == 1)
                startOperation();
            // for the multiplex case
            else if (numberOfConnections > 1)
            {
                //while (p < numberOfConnections)
                //{
                    multiStartOperation();
                //  p++;
                //}
            }
            Thread.Sleep(500);
        }

    }
    // will be called for all ssh connections (in multiplex case)
    private void multiStartOperation()
    {
        string[] command1Array = { "host2", "host2" };
        string[] command2Array = { clickTime + "_h2", clickTime + "_h2" };

        for (int index = 0; index < numberOfConnections; index++)
        {
            // shellArray is an array of SshExec objects
            shellArray[index] = new SshExec(IPAddress, username, password);
            try
            {
                shellArray[index].Connect();
            }
            catch (JSchException se)
            {
                Console.Write(se.StackTrace);
                System.Windows.Forms.MessageBox.Show("Couldn't connect to the specified port.", "Connection Error!");
            }

            sb.Append(shellArray[index].RunCommand(command1Array[index]) + Environment.NewLine);
            // first command is host3, or host4 etc.

            // below is the time consuming command to run 
            string command = "./logcap.sh -c " + command2Array[index] + " -z";
            // sb is a global stringBuilder object,
            // to which the command output is appended
            sb.Append(shellArray[index].RunCommand(command));
        }

    }      

我的问题如下:

当我按下GUI上的开始按钮时,两个连接都应该启动并运行脚本。而在上面给出的代码中,shellArray的第一个索引(由SshExec对象组成)连接起来,准备命令并运行耗时的命令,此时程序返回到UI,甚至没有启动第二个连接。这显然是因为for循环,但我还无法弄清楚如何解决这个问题。

我需要让其他后台工作者与第二台服务器建立并运行第二个命令,这样当我按下GUI上的停止按钮时,所有连接和线程都可以一起停止。

PS:除非用户点击停止,否则命令不会停止运行,停止会向服务器发送Ctrl-C信号。

我对所有多线程和网络概念都比较陌生,所以如果有任何混淆或错误,请告诉我。

度过愉快的一天。

1 个答案:

答案 0 :(得分:0)

感谢您的回答和欢迎。 :) 问题确实无法同时运行多个背景工作者。

我设法解决了这个问题。事实证明,我必须弄清楚的是如何将后台工作者分配给SSH连接。为此,我创建了一个类,如下所示:

    class BGW
    {
        private BackgroundWorker bgw;
        private int index;
        //getters, setters, constructors...
    }

在此之后,我将bwArray(一个BackgroundWorkers数组)转换为一个BGW对象数组。在初始化时,我为每个BGW对象分配了一个索引。

我没有在multiStartOperation()中使用愚蠢的循环,而是向multiStartOperation()发送了一个整数参数,该函数使用该索引来到达分配的后台工作者。

到目前为止似乎有效。 祝你有愉快的一天。