Russian Qt Forum

Qt => Работа с сетью => Тема начата: bztd от Февраль 03, 2010, 08:45



Название: Клиент сервер, Мультитрит, проблемы с чтением
Отправлено: bztd от Февраль 03, 2010, 08:45
собсно создаю сервер, на каждый коннект создаю новый thread и перемещаю туда сокет ( использую nextPendingConnection) через moveToThread.
мне нужно чтобы поток управлял сим сокетом хитрым образом, поэтому стандартная идей connect exec внутри потока не подойдет. сделал так:
Код:
void Thread::run(){
    qDebug()<<"Thread::run ";
    ...
    while(socket->state()==QAbstractSocket::ConnectedState)
    {
        qDebug()<<"socket may read?"<<socket->state();
        if( this->socket->waitForReadyRead(1000))
       {
            int av=socket->bytesAvailable();
            qDebug()<<"Reading from socket bytes: "<<av;
            QByteArray ara;
            do{
                ara= socket->read(av);
            }while(ara.count()<av);
            qDebug()<<ara;
            QString str(ara);
            qDebug()<<"do addString "<<str;
            if(str.isEmpty()) continue;
            ...
        }
        ...

Собсно проблема в следующем - когда клиентом ( в качве клиента пока юзаю netcat ) передаю третий пакет, то bytesAvailable возвращает его правильную длинну, а при попытке его считать - первый раз возвращается "" при любой следущей попытки чтения с сокета - винда уходит в долгий цыкл, из которого прямой путь в SYGSEGV. do while просто временный костыль, до этого было использование readAll. Собсно циклица именно в вызовах read сокета. Конкретней - в ntdll... Это меня сильно смущает и обескураживает...
Прошу помощи :)


Название: Re: Клиент сервер, Мультитрит, проблемы с чтением
Отправлено: ilyagoo от Февраль 03, 2010, 10:09
Цитировать
мне нужно чтобы поток управлял сим сокетом хитрым образом

каким хитрым? чем не нравится
Код:
void Thread::run()
{
    QTcpSocket socket;
    connect( &socket, SIGNAL( readyRead() ), this, SLOT( OnReadyRead() ), Qt::QueuedConnection );
    exec()
}
?


Название: Re: Клиент сервер, Мультитрит, проблемы с чтением
Отправлено: bztd от Февраль 03, 2010, 10:29
Собсно каким именно хитрым, поясню.. в случае с connect exec прийдется делать disconnect =) вот это то мне и не нравится. получается что у QT поток не совсем поток...


Название: Re: Клиент сервер, Мультитрит, проблемы с чтением
Отправлено: BRE от Февраль 03, 2010, 10:33
Собсно каким именно хитрым, поясню.. в случае с connect exec прийдется делать disconnect =) вот это то мне и не нравится. получается что у QT поток не совсем поток...
Что значит придется делать disconnect? Дисконнект чего сигналов или дисконнект соединения? Какие трудности это вызывает?
У Qt нет своих потоков, он использует механизм потоков платформы.


Название: Re: Клиент сервер, Мультитрит, проблемы с чтением
Отправлено: maxxant от Февраль 03, 2010, 10:35
Код:
            QByteArray ara;
            do{
                ara= socket->read(av);
            }while(ara.count()<av);
            qDebug()<<ara;
        ...

наверное хотелось так:
Код:
        ...
                ara += socket->read(av);
        ...


Название: Re: Клиент сервер, Мультитрит, проблемы с чтением
Отправлено: bztd от Февраль 03, 2010, 10:45
я хочу чтобы кроме этого потока еще один поток мог использовать сокет через socketDescriptor. если я соединю кготовность чтения с обработчиком, то второй поток уже не сможет читать и прийдется делать дисконнект с чтения. однако в случае с другой платформой, я бы просто согласовал потоки. по старинке.. собсно мне интересно знать почему я не могу сделать это тут.


Название: Re: Клиент сервер, Мультитрит, проблемы с чтением
Отправлено: maxxant от Февраль 03, 2010, 11:02
я хочу чтобы кроме этого потока еще один поток мог использовать сокет через socketDescriptor. если я соединю кготовность чтения с обработчиком, то второй поток уже не сможет читать и прийдется делать дисконнект с чтения. однако в случае с другой платформой, я бы просто согласовал потоки. по старинке.. собсно мне интересно знать почему я не могу сделать это тут.

bool QAbstractSocket::setSocketDescriptor ( int socketDescriptor, SocketState socketState = ConnectedState, OpenMode openMode = ReadWrite )

Initializes QAbstractSocket with the native socket descriptor socketDescriptor. Returns true if socketDescriptor is accepted as a valid socket descriptor; otherwise returns false. The socket is opened in the mode specified by openMode, and enters the socket state specified by socketState.

Note: It is not possible to initialize two abstract sockets with the same native socket descriptor.


Название: Re: Клиент сервер, Мультитрит, проблемы с чтением
Отправлено: bztd от Февраль 03, 2010, 11:05

наверное хотелось так:
Код:
        ...
                ara += socket->read(av);
        ...
Спасибо за исправление, именно так, однако проблемы это не решает.  Всмысле той с зависанием и нарушением сегментации. внутри read происходит оно.. и я даже без идей почему


Название: Re: Клиент сервер, Мультитрит, проблемы с чтением
Отправлено: ilyagoo от Февраль 03, 2010, 11:28
а в каком потоке находится сокет? ты его случайно не так сделал QTcpSocket( this )?
больше кода:)


Название: Re: Клиент сервер, Мультитрит, проблемы с чтением
Отправлено: maxxant от Февраль 03, 2010, 11:41
Спасибо за исправление, именно так, однако проблемы это не решает.  Всмысле той с зависанием и нарушением сегментации. внутри read происходит оно.. и я даже без идей почему

QObject Reentrancy

QObject is reentrant. Most of its non-GUI subclasses, such as QTimer, QTcpSocket, QUdpSocket, QHttp, QFtp, and QProcess, are also reentrant, making it possible to use these classes from multiple threads simultaneously. Note that these classes are designed to be created and used from within a single thread; creating an object in one thread and calling its functions from another thread is not guaranteed to work.

Мысль только одна: проблема с потоками. Пробуйте написать сначала попроще, типа как примерах.


Название: Re: Клиент сервер, Мультитрит, проблемы с чтением
Отправлено: bztd от Февраль 03, 2010, 13:17
Спасибо, буду думать, искать.
 
Насчет потоков, сокету было сделано setParent(0), moveToThread(this);