постоянно проверять, прослушивает ли сервер данный порт с помощью C # - PullRequest
1 голос
/ 22 марта 2012

благодаря этому ответу я смог определить, прослушивает ли Сервер данный порт или нет:

Как настроить время ожидания подключения к сокету

сейчас я 'Я пытаюсь создать бесконечный цикл, который будет загружен при событии form_load и будет постоянно проверять, слушает ли сервер.

вот мой код:

            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IAsyncResult result = socket.BeginConnect("192.168.0.131", 1095, null, null);

            bool success = result.AsyncWaitHandle.WaitOne(500, true);

            if (!socket.Connected)
            {label3.Text = "can't use"; socket.Close();}
            else
            {label3.Text = "start action";}

Если я добавлю следующий кодв событие "on_button_click" - все работает нормально (кроме - мне нужно нажимать кнопку каждый раз, когда я хочу обновить статус)

и когда я создаю бесконечный цикл - я не получаю никаких результатов вообще:

while (true)
        {
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IAsyncResult result = socket.BeginConnect("192.168.0.131", 1095, null, null);

            bool success = result.AsyncWaitHandle.WaitOne(500, true);

            if (!socket.Connected)
            {
                label3.Text = "can't use";
                socket.Close();
            }
            else
            {
                //success = true;
                label3.Text = "start action";
                socket.Close();
            }
        }

Я думаю, это как-то связано с многопоточностью, но я просто не могу понять это.В чем может быть проблема?

Редактировать:

Решение по таймеру:

private void Form1_Load_1(object sender, EventArgs e)
        {
            System.Windows.Forms.Timer MyTimer = new System.Windows.Forms.Timer();
            MyTimer.Interval = (200);
            MyTimer.Tick += new EventHandler(MyTimer_Tick);
            MyTimer.Start();
        }

        public void MyTimer_Tick(object sender, EventArgs e)
        {

                Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IAsyncResult result = socket.BeginConnect("192.168.0.131", 1095, null, null);

                bool success = result.AsyncWaitHandle.WaitOne(500, true);

                if (!socket.Connected)
                {

                    label3.Text = "can't use";
                    socket.Close();
                    //throw new ApplicationException();
                }
                else
                {
                    //success = true;
                    label3.Text = "start action";
                    socket.Close();
                }   

        }

Ответы [ 5 ]

2 голосов
/ 22 марта 2012

Вы можете добавить объект Таймер к вашей форме. Запустите таймер при загрузке формы, и в событии timer Tick запустите ваш код в бесконечном цикле.

Примечание: НЕ включайте цикл while(true), только код внутри цикла. Вы действительно не хотите бесконечный цикл в вашем потоке GUI:)

EDIT
Я все еще думаю, что вам, возможно, придется подумать о редизайне поведения приложения, но это должно быть лучше, чем таймер, который я предложил ранее

Несколько лучший подход к таймеру (который должен решить проблему с задержкой пользовательского интерфейса) - добавить в свой пользовательский интерфейс BackgroundWorker . Добавьте DoWork метод, подобный этому:

void DoWork(object sender, DoWorkEventArgs e)
{
    while(!_bw.CancellationPending)
    {
        // Do your socket connection stuff

        // you can either update some member variables and call
        // the progresschanged method or you can use a BeginIvoke call
        // to update the labels, you CANNOT update the labels in this method
        if (!_bw.CancellationPending)
        {
            // Checking the cancel pending before sleeping so that we don't sleep
            // while a cancel is pending. There are better ways to do this with
            // event handles, but this should get you off and running.
            Thread.Sleep(1000);
        }
    }
    e.Cancel = true;
}

Примечание. Если вы использовали .Net 4.0, вы можете рассмотреть возможность использования фабрики задач и токена отмены, а не BackgroundWorker, но любой из них должен заставить вас работать.

1 голос
/ 22 марта 2012

Если этот цикл выполняется в потоке графического интерфейса, он заблокирует графический интерфейс, поскольку он не сможет получать пользовательский ввод.

Вы должны выполнить код в другом потоке, а затем обновить пользовательский интерфейс, используя Invoke или BeginInvoke. Что-то вроде:

Thread t = new Thread(
   o => 
   {
    while (true)
    {
        Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        IAsyncResult result = socket.BeginConnect("192.168.0.131", 1095, null, null);

        bool success = result.AsyncWaitHandle.WaitOne(500, true);

        if (!socket.Connected)
        {

            label3.BeginInvoke((Action)(() => { label3.Text = "can't use"; }));
            socket.Close();
        }
        else
        {
            //success = true;
            label3.BeginInvoke((Action)(() => { label3.Text = "start action"; }));
            socket.Close();
        }
    }
  });
t.Start();
0 голосов
/ 22 марта 2012

Требуется время для закрытия TCP-соединения.Каждый раз, когда вы подключаетесь к удаленному серверу и вызываете close на сокете, происходит квитирование TCP.

См. Это руководство http://www.tcpipguide.com/free/t_TCPConnectionTermination-2.htm

Избегайте открытия / закрытия сокетов с такой высокой скоростьюполсекунды).Вы можете создать длинный список TCP-соединений на удаленном сервере, которые находятся в состоянии близкого ожидания, и если это не ваш сервер, то это может рассматриваться как атака.

Для неудачных соединений этона самом деле не проблема.

0 голосов
/ 22 марта 2012

Я не думаю, что вы можете создать экземпляр объекта более одного раза.Возможно, вам придется поставить

Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

перед циклом while

Чтобы лучше диагностировать вашу проблему, вы также можете использовать

Console.WriteLine("Can't use");
Console.WriteLine("Start action");

, чтобы увидеть, есть ли проблема с многопоточностьюили нет (с графическим интерфейсом не обновляется)

0 голосов
/ 22 марта 2012

Недостаточно кода, чтобы рассказать все, что нам нужно знать, но вот начало.

Работает ли этот цикл в другом потоке или он просто присутствует в событии button_click?

  • Если он не запущен в другом потоке, вероятно, вы нажмете кнопку, и приложение будет зависать, а пользовательский интерфейс никогда не будет обновляться ... Необходимо установитьдля запуска в другом потоке.

    • Вы можете бросить команду Application.DoEvents () сразу после обновления метки, чтобы разморозить пользовательский интерфейс и обновить метку, но это не то, что нужно делатьв живом коде.Вы захотите создать новую ветку для чека в производственном приложении.Application.DoEvents в этом сценарии может вызвать проблемы.
  • Если он работает в другом потоке, вам, вероятно, потребуется использовать InvokeRequired для обновления меток в форме.

В этой статье показан код для запуска кода в другом потоке и правильного использования InvokeRequired.

...