Russian Qt Forum
Ноябрь 23, 2024, 22:54 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Опрос большого числа абонентов по TCP  (Прочитано 7971 раз)
texnik
Гость
« : Октябрь 08, 2010, 12:05 »

Здравствуйте все.
Проблема следующая. Есть приложение, которое должно периодически опрашивать большое количество абонентов по протоколу TCP, т.е высылать им некие запросы и получать на них ответы. Для каждого абонента набор запросов различный.

Сейчас я делаю это так. Формируется пул потоков, каждый из которых обрабатывает одно соединение с абонентом и работу с ним. Сами пакеты формируются отдельно и передаются для отсылки через очередь запросов, полученные пакеты закладываются в очередь ответов и обрабатываются тоже отдельно.

Поток вида
tcpclientyhread.h
Код:
#include <QHostAddress>
#include <QTcpSocket>

class TcpClientThread : public QThread
{
    Q_OBJECT
public:
    TcpClientThread();

    void run();

};
tcpclientthread.cpp
Код:
#include "tcpclientthread.h"

TcpClientThread::TcpClientThread() : QThread()
{
}

void TcpClientThread::run()
{    
    QTcpSocket socket;

    socket.connectToHost(ip,port);
    if (socket.waitForConnected(3000))
    {        
        QByteArray outBlock;
        //здесь забираю пакет из очереди запросов
        socket.write(outBlock);

        if (socket.waitForReadyRead(3000))
        {
              QByteArray inBlock = socket.readAll();    
              //выкидываю его во внешнюю очередь ответов              
              socket.disconnectFromHost();                    
              if (socket.state() != QAbstractSocket::UnconnectedState)
              {
                   socket.waitForDisconnected(100);
              }
       }
       else
       {
            //обработка ситуации ошибки ожидания ответа
            socket.disconnectFromHost();
            if (socket.state() != QAbstractSocket::UnconnectedState)
            {
               socket.waitForDisconnected(100);                    
            }
        }
    }
    else
    {
        //обработка ситуации ошибки ожидания подключения
    }
    socket.close();
}

Возникает проблема, когда открывается множество соединений TCP, имеющих состояние TIME_WAIT (netstat), для закрытия которых требуется значительное в рамках интенсивности опроса время. А затем весь опрос "умирает". Полный цикл опроса всех абонентов должен производится хотя в рамках 10 секунд.

Создавать отдельное соединение на каждый абонент не могу из-за количества абонентов, превышающего лимит по соединениям.

Нужен ваш совет. Заранее спасибо.
« Последнее редактирование: Октябрь 08, 2010, 14:05 от texnik » Записан
vunder
Гость
« Ответ #1 : Октябрь 08, 2010, 13:29 »

Думаю, все-таки нужно создавать несколько соединений, но не все количество абонентов, а пачками, скажем по 10 штук. Это обычная практика. Сканеры портов, например, именно так и делают: задается максимальное количество потоков, если в очереди есть необработанные клиенты, то проверяется, можно ли создать для него новый поток. Если можно, то поток создается. При завершении работа одного из потока снова проверяется, если ли в очереди клиенты.
Записан
texnik
Гость
« Ответ #2 : Октябрь 08, 2010, 14:09 »

Дело в том, что опросить за период нужно все абоненты, и этот период меньше чем период ожидания для удаления соединения операционной системой.
А если я установлю допустим 10 постоянных соединений, то это будет только 10 абонентов.
Записан
vunder
Гость
« Ответ #3 : Октябрь 08, 2010, 19:53 »

Смысл в том, что после обслуживания очередного абонента можно перейти к опросу очередного. Так мы получем несколько потоков для опроса большого числа клиентов
Записан
texnik
Гость
« Ответ #4 : Октябрь 09, 2010, 12:16 »

Смысл в том, что после обслуживания очередного абонента можно перейти к опросу очередного. Так мы получем несколько потоков для опроса большого числа клиентов
Ну вообще то  я так и делаю. Проблема не в создании множества потоков (пул потоков ограничен), а в том, что после того как производится disconnectFromHost текущее TCP соединение висит в состоянии TIME_WAIT еще более минуты и через некоторое время таких соединений становится слишком много.
Записан
SABROG
Гость
« Ответ #5 : Октябрь 09, 2010, 21:18 »

Проблема не в создании множества потоков (пул потоков ограничен), а в том, что после того как производится disconnectFromHost текущее TCP соединение висит в состоянии TIME_WAIT еще более минуты и через некоторое время таких соединений становится слишком много.
Насколько я знаю это стандартное поведение протокола TCP/IP и относится ко всем программам, после закрытия сокета он остается открытым какое-то время для операционной системы, чтобы гарантировать доставку пакетов с информацией о завершении соединения. Qt тут не при чем.
Записан
texnik
Гость
« Ответ #6 : Октябрь 10, 2010, 01:55 »

Может подскажете в какую сторону "курить"?)
Записан
SABROG
Гость
« Ответ #7 : Октябрь 10, 2010, 10:22 »

превышающего лимит по соединениям
А как это выглядит? Вы опросили 1000 абонентов, закрыли все соединения и пытаетесь заново их опросить, а ОС не дает, так как закрытые сокеты остались открытыми где-то внутри ОС и висят с флагом TIME_WAIT?

Создавать отдельное соединение на каждый абонент не могу из-за количества абонентов, превышающего лимит по соединениям.
Тут я не понял. А как можно не создавать отдельное соединение/сокет на каждого клиента? Broadcasting, который дальше шлюза не уйдет?
Записан
texnik
Гость
« Ответ #8 : Октябрь 10, 2010, 19:56 »

А как это выглядит? Вы опросили 1000 абонентов, закрыли все соединения и пытаетесь заново их опросить, а ОС не дает, так как закрытые сокеты остались открытыми где-то внутри ОС и висят с флагом TIME_WAIT?
Именно так и выглядит, при опросе для каждого нового абонента создается соединение, производится обмен, потом соединение закрывается. После закрытия соединения сокеты висят с флагом TIME_WAIT некоторое время.

Цитировать
Тут я не понял. А как можно не создавать отдельное соединение/сокет на каждого клиента? Broadcasting, который дальше шлюза не уйдет?
Здесь вероятно я не правильно выразился - я имел в виду то, что возможное количество абонентов значительно больше количества сокетов в ОС и нельзя создать постоянное соединения для каждого абонента. Получается что надо работать с абонентами последовательно, высвобождая сокеты.
Записан
SABROG
Гость
« Ответ #9 : Октябрь 10, 2010, 22:00 »

Получается что надо работать с абонентами последовательно, высвобождая сокеты.
Это понятно. Непонятно в чем проблема. Просто хочется, чтобы не висели в netstat или всё-таки ОС не дает после определенного количества попыток снова соединяться и программа перестает корректно работать?
Записан
texnik
Гость
« Ответ #10 : Октябрь 11, 2010, 11:52 »

Получается что ОС не дает соединяться снова - соответственно и программа перестает корректно работать. Больше не происходит подключения.
Записан
SABROG
Гость
« Ответ #11 : Октябрь 11, 2010, 12:23 »

Получается что ОС не дает соединяться снова - соответственно и программа перестает корректно работать. Больше не происходит подключения.

Это известная проблема p2p клиентов. Для устранения патчат файлик tcpip.sys, чтобы уменьшить время освобождения сокетов протоколом. Другой вариант поставить минимальную задержку перед следующим сканированием одного и того же IP адреса в 300 секунд.
Записан
texnik
Гость
« Ответ #12 : Октябрь 11, 2010, 13:12 »

Все ясно. Большое спасибо.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.103 секунд. Запросов: 21.