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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: QTcpServer при высокой нагрузке  (Прочитано 2643 раз)
RankoR
Гость
« : Ноябрь 29, 2010, 22:32 »

Приветствую!
Пишу приложение, суть которого заключается в следующем:
Клиент коннектится к моему серверу, сервер создает новый сокет, который коннектит к другому серверу, и перекидывает данные от клиента к другому серверу (и обратно). В общем-то похоже на проброс портов или прокси.
Клиентские (полученные из QTcpServer) и серверные сокеты присоединены к одним и тем же сигналам onReadyRead и onDisconnected.

Проблема заключается вот в чем. При 10-50-70 одновременных подключениях к серверу все ок. Однако при сотне начинаются проблемы - клиент коннектится, но сигналы readyRead и disconnected перестают работать, в итоге я получаю кучу сокетов, висящих мертвым грузом, и сервер, не делающий ничего, но отличненько жрущий память. В чем может быть проблема? Неужели QTcpServer не выдерживает такой (не такой уж и большой) нагрузки?
Записан
voral
Гость
« Ответ #1 : Ноябрь 30, 2010, 09:51 »

Вы по потокам разделяете?
с "другим" сервером одно общее соединение или 1:1?
« Последнее редактирование: Ноябрь 30, 2010, 10:28 от voral » Записан
RankoR
Гость
« Ответ #2 : Ноябрь 30, 2010, 15:41 »

Код:
void QListener::onConnection()
{
    /* Getting the pending connection */
    QTcpSocket *clientSocket = serverSocket.nextPendingConnection();

    if ( ! clientSocket )
        return;

    QString ip = clientSocket->peerAddress().toString();

    /* Checking if connection is allowed */

    bool isInCache = false;
    QUserInfo userInfo;

    userInfo = userInfoMap.value(ip, userInfo);

    if ( ! userInfo.user.isEmpty() )
    {
        if ( userInfo.lastUpdate.secsTo(QTime::currentTime()) < (60 * 10)  )
            isInCache = true;
    }

    bool isAllowed = true;

    /* If user is not in cache - get it from SQL and add to cache */
    if ( ! isInCache )
    {
        userInfo.user.clear();

        if ( ! db.open() )
            qDebug() << "Failed to open DB!";

        QSqlQuery *sqlQuery = NULL;
        try
        {
        sqlQuery = new QSqlQuery(db);
        } catch(...)
        {
            qDebug() << "Exception! [1]";
            return;
        }

        if ( ! sqlQuery->exec(QString("SELECT user, threads FROM users WHERE ip='%1'").arg(ip)) )
        {
            qDebug() << "Query failed:" << sqlQuery->lastError().text();
            isAllowed = false;
        }

        if ( sqlQuery->next() && isAllowed )
        {
            userInfo.user = sqlQuery->value(0).toString();
            userInfo.maxThreads = sqlQuery->value(1).toInt();
            userInfo.lastUpdate = QTime::currentTime();

            userInfoMap.remove(ip);                     // Remove the old user info from the cache
            userInfoMap.insert(ip, userInfo);           // Insert user info to the cache
        } else
            isAllowed = false;

        sqlQuery->finish();
        delete sqlQuery;
        db.close();

        if ( isAllowed )
            qDebug() << "Cache record for" << ip << "is deprecated and was updated";
    }

    /* Check if threads limit is reached */
    qint32 connectionsCount = connectionsList.count(ip);

    if ( connectionsCount >= userInfo.maxThreads )
    {
        connectionsList.removeAt(connectionsList.indexOf(ip));
    }

    /* If not allowed - disconnect */
    if ( ! isAllowed )
    {
        clientSocket->disconnectFromHost();
        clientSocket->deleteLater();
        return;
    }

    /* Trying to connect to the proxy */
    QTcpSocket *proxySocket = NULL;
    try
    {
    proxySocket = new QTcpSocket;
    } catch(...)
    {
        qDebug() << "Exception (2)!";
        clientSocket->disconnectFromHost();
        clientSocket->deleteLater();
        return;
    }

    if ( ! proxySocket )
    {
        clientSocket->disconnectFromHost();
        clientSocket->deleteLater();
        return;
    }

    /* Get the proxy host & port from the DB */

    if ( proxiesCount == 0 )
    {
        qDebug() << "Proxies count == 0!";
        clientSocket->disconnectFromHost();
        clientSocket->deleteLater();
        return;
    }

    mutex.lock();
    QString host = proxiesList.at(currentProxy);
    quint16 port = portsList.at(currentProxy);

    if ( currentProxy >= (proxiesCount - 1) )
        currentProxy = 0;
    else
        currentProxy++;
    mutex.unlock();


    /* Connect to the proxy */

    proxySocket->connectToHost(host, port);

    if ( ! proxySocket->waitForConnected(5000) )
    {
        qDebug() << "Failed to connect to the proxy!";
        clientSocket->disconnectFromHost();
        clientSocket->deleteLater();
        return;
    }

    connectionsCount++;
    connectionsList.append(ip);
    qDebug() << "New connection accepted! " << connectionsCount << "connections for this IP";
    qDebug() << "Total:" << socketsMap.count() << "connections";

    /* Add sockets to the map and connect to the slots */
    clientSocket->setSocketOption(QAbstractSocket::KeepAliveOption, 1);
    proxySocket->setSocketOption(QAbstractSocket::KeepAliveOption, 1);

    socketsMap[clientSocket] = proxySocket;

    connect(clientSocket, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
    connect(proxySocket, SIGNAL(readyRead()), this, SLOT(onReadyRead()));

    connect(clientSocket, SIGNAL(disconnected()), this, SLOT(onDisconnected()));
    connect(proxySocket, SIGNAL(disconnected()), this, SLOT(onDisconnected()));
}

Вот код, немного индусский, ибо писался в спешке.
Функция выполняется до конца.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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