crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> Асинхронный однопоточный сервер и обработка данных, как создать буффер данных для каждого подключившегося клиента
demiurg
  опции профиля:
сообщение 3.5.2011, 23:21
Сообщение #1


Студент
*

Группа: Новичок
Сообщений: 11
Регистрация: 27.4.2011
Пользователь №: 2639

Спасибо сказали: 0 раз(а)




Репутация:   0  


Вообщем сабж. Есть однопоточный асинхронный сервер завязанный на БД и на который в теории может подключится одновременно около 100 клиентов. Но перед тем как добавлять в базу данных нужно реализовать несложный протокол обработки , а для этого нужно чтобы для каждого клиента был свой буффер данных ( данные могут идти с задерками) . Никак не вьеду как это реализовать покрасивее. Пытался создать класс типа

class My_client: public QTcpServer{
    Q_OBJECT
public:
    My_client(QObject *parent=0);
    ~My_client();
    QTcpSocket *cl_sock;
    QString buffer;

   };



Но тогда нет согласования *cl_sock и buffer в строчке обработки слотов приёма данных и удаления сокета client->cl_sock = qobject_cast<QTcpSocket*>(sender());

Помогите кто сталкивался пожалуйста :clapping: Я уже запутался :)

Сервер взял типовой из примеров Земского.


Хм, перечитал непонятно наверно пробему объяснил.

Собственно данные идут в разрыв. Т.е. клиент может перестать передавать , а потом продолжить. Тогда в буффер объявленный в конструкторе сервера (глобальный) могут помимо уже записанных данных одного клиента попасть данные другого. :rolleyes: Код могу привести но его много.

То что я пытался сделать , но это видать не то :unsure:

Раскрывающийся текст

#include <QtCore>
#include <QtNetwork>
#include <QtSql>

class My_client: public QTcpServer{
    Q_OBJECT
public:
    My_client(QObject *parent=0);
    ~My_client();
    QTcpSocket *cl_sock;
    QString buffer;

   };

class EchoServer : public QTcpServer {
    Q_OBJECT
public:
    EchoServer(QObject *parent=0);
    ~EchoServer();
    bool start();

    QList <My_client*> m_clients;
    QSqlDatabase db;
    QSqlQuery *sql;

    QString temp;
    ///
    quint8 year;
    quint8 mongth;
    quint8 day;
    quint8 hour;
    quint8 minute;
    quint16 Pnum;
    QString IMEI;
    QString Vnum;
    quint32 work_hour;
    QString energy;
    QString vol1;
    QString vol2;
    QString consumption;
    QString temp1;
    QString temp2;
    qreal battary;
    QString sim_number;
    qreal money;


    ///

    
public slots:
    void addConnection();
    void removeConnection();
    void onRead();
    void displayError(QAbstractSocket::SocketError);
};



Раскрывающийся текст
#include <iostream>
#include <QtCore>
#include <QtNetwork>
#include "echoserver.h"

#define STR(s) ((QTextCodec::codecForLocale()->fromUnicode(s)).constData())
using namespace std;

EchoServer::EchoServer(QObject *parent)
          : QTcpServer(parent)
{
}

My_client::My_client(QObject *parent)
          : QTcpServer(parent){}

My_client::~My_client(){}

EchoServer::~EchoServer() {
    while (!m_clients.isEmpty()) {
        My_client *client = m_clients.takeFirst();
        client->cl_sock->write(QTextCodec::codecForLocale()->fromUnicode(
                        QObject::tr("\nСервер отключается") + 0x0d ) );
        client->cl_sock->flush();
        client->cl_sock->close();
        client->cl_sock->deleteLater();
    }
}

bool EchoServer::start() {
    QHostAddress addr;
    QSqlDatabase db =  QSqlDatabase::addDatabase("QMYSQL");
        db.setHostName("localhost");
        db.setDatabaseName("test");
        db.setUserName("root");
        db.setPassword("qwe");
        db.setPort(3309);
    bool connected = db.open();
        if (!connected)
        {
        cout << STR(QObject::tr("Не могу запустить БД"));
        }
        db.close();


    if ( !listen(QHostAddress::Any, 5678) ) {
        cout << STR(QObject::tr("Не могу запустить сервер: %1\n")
                   .arg( errorString() ) );
        close();
        return false;
    }
    connect(this, SIGNAL(newConnection()), this, SLOT(addConnection()));
    cout << STR(QObject::tr("Сервер запущен\n"));
    return true;
}

void EchoServer::addConnection() {
         QSqlQuery sql = QSqlQuery();
     if(!db.isOpen())
         {
       QSqlDatabase db =  QSqlDatabase::addDatabase("QMYSQL");
       db.setHostName("localhost");
       db.setDatabaseName("test");
       db.setUserName("root");
       db.setPassword("qwe");
       db.setPort(3309);
        bool connected =db.open();
        if (!connected)
        {
        cout << STR(QObject::tr("Не могу запустить БД"));
        }
        else
        {
        cout << STR(QObject::tr("Переподключение"));
        }
    }
    My_client *client = new My_client();

    client->cl_sock = nextPendingConnection();
    connect(client->cl_sock, SIGNAL(disconnected()),
            this, SLOT(removeConnection()));
    connect(client->cl_sock, SIGNAL(readyRead()), this,  SLOT(onRead()));
    connect(client->cl_sock, SIGNAL(error(QAbstractSocket::SocketError)),
            this, SLOT(displayError(QAbstractSocket::SocketError)));
    client->cl_sock->write(QTextCodec::codecForLocale()->fromUnicode(
                         QObject::tr("Hello! Привет!") + 0x0d ) );
    QHostAddress addr = client->cl_sock->peerAddress();
    cout << STR(QObject::tr("Подключился новый клиент с адреса %1\n")
                         .arg( addr.toString() ));
    m_clients.append(client);
}

void EchoServer::removeConnection(){
    My_client *client = new My_client();
    client->cl_sock = qobject_cast<QTcpSocket*>(sender());
    QHostAddress addr = client->cl_sock->peerAddress();
    cout << STR(QObject::tr("Клиент %1 отключен\n")
                         .arg( addr.toString() ));
    m_clients.removeAt(m_clients.indexOf(client));
    client->deleteLater();
}

void EchoServer::onRead() {
    //QString buffer;
    quint16 buffer_index;
    My_client *client = new My_client();
    client->cl_sock = qobject_cast<QTcpSocket*>(sender());
    QByteArray block = client->cl_sock->readAll();
    QString s = QTextCodec::codecForTr()->toUnicode(block.data());
    //if ( s.contains(0x08) ) {
    //    cout << STR(QObject::tr("\nСервер остановлен\n"));
     //   deleteLater();
     //   QCoreApplication::instance()->exit();
     //   return;
    //}
    client->buffer.append(s);
    QHostAddress addr = client->cl_sock->peerAddress();
    if (s.contains('$'))
    {
    temp.clear();
    buffer_index=0;
    while (client->buffer[buffer_index]!='@'){buffer_index++;};
    buffer_index++;
    while (client->buffer[buffer_index]!='#'){temp.append(client->buffer[buffer_index]);buffer_index++;};
    Pnum=temp.toInt();
    temp.clear();
    buffer_index++;
    while (client->buffer[buffer_index]!='$'){temp.append(client->buffer[buffer_index]);buffer_index++;};
    IMEI=temp;
    cout << STR(QObject::tr("Получены новые данные от клиента %1: %2\n")
                         .arg(Pnum) . arg(IMEI) );
    client->buffer.clear();
    }

     if ( s.contains('*') )
    {
     QSqlQuery sql = QSqlQuery();
     sql.prepare("INSERT INTO test1 (p1)""VALUES(:p1)");
     sql.bindValue(":p1", client->buffer);
     sql.exec();
     cout << STR(QObject::tr("Получены новые данные от клиента %1: %2\n")
                         .arg( addr.toString() ) . arg(client->buffer) );
     client->buffer.clear();
     client->cl_sock->write(QTextCodec::codecForLocale()->fromUnicode(
                         QObject::tr("RECEIVE_OK") + 0x0d+0x0a ) );
     }

     //client->write(QTextCodec::codecForLocale()->fromUnicode(s));
     }

void EchoServer::displayError(QAbstractSocket::SocketError){
    cout << STR(QObject::tr("\nОшибка: %1\n").arg(errorString()));
}

//===============================================
int main(int argc, char **argv) {
    QCoreApplication app(argc, argv);
    QTextCodec *incodec = QTextCodec::codecForName("CP1251");
    QTextCodec *outcodec = QTextCodec::codecForName("CP866");
    QTextCodec::setCodecForTr(incodec);
    QTextCodec::setCodecForLocale(outcodec);

    EchoServer server;
    server.start();
    return app.exec();
}
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
xls
  опции профиля:
сообщение 4.5.2011, 12:51
Сообщение #2


Студент
*

Группа: Участник
Сообщений: 44
Регистрация: 6.9.2010
Пользователь №: 2013

Спасибо сказали: 7 раз(а)




Репутация:   2  


Цитата
Т.е. клиент может перестать передавать , а потом продолжить. Тогда в буффер объявленный в конструкторе сервера (глобальный) могут помимо уже записанных данных одного клиента попасть данные другого

Может, идентифицировать клиента по IP-адресу и дописывать в буфер, созданный в конструкторе? Или их по несколько штук на хост может быть?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
demiurg
  опции профиля:
сообщение 4.5.2011, 13:06
Сообщение #3


Студент
*

Группа: Новичок
Сообщений: 11
Регистрация: 27.4.2011
Пользователь №: 2639

Спасибо сказали: 0 раз(а)




Репутация:   0  


Теоретически возможно и сотня.

Решил проблему через QMap

Как бы теперь протестировать ?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
PAFOS
  опции профиля:
сообщение 7.6.2011, 7:47
Сообщение #4


Активный участник
***

Группа: Участник
Сообщений: 258
Регистрация: 27.12.2010
Из: Дмитров
Пользователь №: 2309

Спасибо сказали: 29 раз(а)




Репутация:   8  


Вообще, на будущее, лучше через QMap такие вещи не делать ибо по-любому надо будет еще какой-нибудь параметр привязать к клиенту.

Делай класс, который описывает эти параметры + владеет указателем на объект QTcpSocket.
И не забудь определить для этого класса операторы == и < для того, чтобы использовать его(класс) в контейнерах типа QList<> QVector<> и др.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 25.4.2024, 9:13