Russian Qt Forum

Qt => Работа с сетью => Тема начата: VMind от Август 28, 2013, 13:33



Название: QTcpSocket QThreads проблемы с чтением
Отправлено: VMind от Август 28, 2013, 13:33
Добрый день.
Собственно, клиент-сервер на QTcpSocket.
Сервер должен многопоточно обрабатывать приходящие сообщения от клиентов.
Проблема - С сокета не получается читать (количество доступных байт - 0), хотя сигнал readyRead() появляется.

Немного кода

В конструктор класса-наследника QThread передается дескриптор.
Код:
MyThread::MyThread(int intsocket)
{
    socket = new QTcpSocket;
    this -> intsocket = intsocket;
    socket->setSocketDescriptor(intsocket);
    blocksize = 0;
}
В run() - собственно попытка вытащить из сокета сообщение.
Код:
void MyThread::run()
{
    std::cout << socket->bytesAvailable() << std::endl;
    // попробуем вытащить размер
    QDataStream stream(socket);
    if (blocksize == 0) {
        if (socket -> bytesAvailable() < (int)sizeof(qint64))
            return;
        stream >> blocksize;
    }
    std::cout << blocksize << std::endl;
    // Теперь ожидаем сообщение заданного размера
    if (socket -> bytesAvailable() < blocksize)
        return;
    stream >> message;
    blocksize = 0;

    // Сообщение получено - обработаем.
    IncomingMesssage();
}

QTcpServer и обработка его сигнала connected().
Код:
void MyServer::NewConnect()
{
//    std::cout << "New connection:" << std::endl;
    client = server.nextPendingConnection();
    int intsocket = client -> socketDescriptor();
    threads[intsocket] = new MyThread(intsocket);
    connect(client, SIGNAL(readyRead()), threads[intsocket], SLOT(start()), Qt::DirectConnection);
    connect(client, SIGNAL(error(QAbstractSocket::SocketError)), threads[intsocket], SLOT(SocketError(QAbstractSocket::SocketError)), Qt::DirectConnection);
}

Ну и вопрос - как решать проблему?


Название: Re: QTcpSocket QThreads проблемы с чтением
Отправлено: popper от Август 28, 2013, 15:16
Лучше сначала сделать однопоточный сервер и убедиться, что данные в сокет действительно приходят.
Передавать в поток лучше указатель на сокет, никакие сигналы в потоке ловить не нужно.


Название: Re: QTcpSocket QThreads проблемы с чтением
Отправлено: mutineer от Август 28, 2013, 15:46
1) твой сокет живет не в потоке, которым владеет MyThread, а в основном потоке приложения (потому что создан он в конструкторе, который выполняется в главном потоке)
2) На каждый readyRead запускать поток это плохо и медленно. Запускай поток один раз, а потом просто в нем реагируй на readyRead


Название: Re: QTcpSocket QThreads проблемы с чтением
Отправлено: demaker от Август 29, 2013, 17:13
Сервер должен многопоточно обрабатывать приходящие сообщения от клиентов.

Наверное вот так лучше будет
Код
C++ (Qt)
 
class Server: public QTcpServer
{
Q_OBJECT
Server(QObject *parent = 0);
 
protected:
void incomingConnection(int socketDescriptor);
QList<Thread*> m_threads;
 
public Q_SLOTS:
void removeThread();
}
 
 
 
void Server:: incomingConnection(int socketDescriptor){
 
Thread*thread = new Thread(socketDescriptor,this);
connect(thread,SIGNAL(finished),this,SLOT(removeThread()),Qt::DirectConnection);
m_threads.append(thread);
thread->start();
 
}
 
class Thread: public QThread
{
Q_OBJECT
 
public:
Thread(int socketDescriptor,QObject*parent = 0);
 
private:
int m_socketDescriptor;
QTcpSocket *m_client;
QHostAddress m_addr;
 
public Q_SLOTS:
 
void onRead();
void onDisconect();
 
Q_SIGNALS:
void error(QAbstractSocket::SocketError)
protected:
void run();
}
 
 
void Thread::run()
{
 
m_client = new QTcpSocket();
 
if(!m_client -> setSocketDescriptor(m_socketDescriptor)){
 
}
 
connect(m_client,SIGNAL(readyRead()),this,SLOT(onRead));
...
}
 
void Thread::onRead(){
 
QByteArray block = m_client->readAll();
 
}
 

Основная идея такая.