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

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

Страниц: 1 2 [3] 4   Вниз
  Печать  
Автор Тема: QTCPSocket в отдельном потоке.  (Прочитано 29955 раз)
stix357
Гость
« Ответ #30 : Январь 11, 2017, 11:48 »

stix357, просто QTcpSocket смысла нет переносить в поток. Да и вообще, тебе тут поток не нужен, если работаешь с сокетом сигналами/слотами. Вот тебе пример с moveToThread.
----
Что непонятно, спрашивай. Писал в браузере - возможны ошибки.

Спасибо, пока сижу перевариваю.
Записан
stix357
Гость
« Ответ #31 : Январь 11, 2017, 12:39 »

stix357, просто QTcpSocket смысла нет переносить в поток. Да и вообще, тебе тут поток не нужен, если работаешь с сокетом сигналами/слотами.
Тут у меня затык в том, что клиент с QTcpSocket получает данные непрерывно с контроллера, пока не получит код завершения.
Обрабатывать данные надо по мере поступления очередных пакетов.
Поэтому приходится на сигнал сокета
Код
C++ (Qt)
SIGNAL(readyRead())
вешать дурную конструкцию типа
Код
C++ (Qt)
void TCPClientQt::slotReadyRead()
{
....
isEnd=false;
isCmd=false;
 while(true)
 {
    currArr=read(now_BytesAvailable);
       totalBytesRecived=totalBytesRecived+now_BytesAvailable;
           if(now_BytesAvailable < sizeCmd && !currArr.contains(m_AnswerStop.toAscii())){
 
.//..
               isCmd=true;
               break;
           }else{
//....
           }
           arrReadBlock.append(currArr);
//...
                  if(currArr.contains(m_AnswerStop.toAscii())){              
//..
               break;
       waitForReadyRead(900);//
}
 //
 if(isEnd)
 {
    m_StrInfo=QTime::currentTime().toString("hh:mm:ss.zzz")
                    +" R bytes: "
                    +QString::number(totalBytesRecived);
    emit sig_newInfo();
return;
}
 
А пока данные принимаются - если в основном потоке, то он висит.
« Последнее редактирование: Январь 11, 2017, 13:07 от Пантер » Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #32 : Январь 11, 2017, 13:09 »

waitForReadyRead(900); фтопку, остальное отрабатывает доли секунды.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
stix357
Гость
« Ответ #33 : Январь 11, 2017, 14:32 »

waitForReadyRead(900); фтопку
Не, к сожалению низя, тогда не успевает очередной пакет получить и нагло из цикла выходит на проверке в начале цикла
Код
C++ (Qt)
       if(now_BytesAvailable < sizeof(quint16)){
           m_StrInfo=QTime::currentTime().toString("hh:mm:ss.zzz")+" 0 bytes";
           emit sig_newInfo();
           break;
 
waitForReadyRead(500) - это минимально
Сам не могу понять почему, разве что сеть WiFi и максимальная скорость канала 56 кбит у радиомодуля при контроллере.

Вопрос возник: обязательно сигналы со слотами после создания потомка  QTcpSocket связывать во внешней среде, так сказать?
я создал потомка
Код
C++ (Qt)
TCPClientQt::TCPClientQt(QObject *parent): QTcpSocket(parent)
 
и у него в конструкторе прописал:
Код
C++ (Qt)
connect(this, SIGNAL(connected()), SLOT(slotConnected()),Qt::AutoConnection);
connect(this, SIGNAL(disconnected()), SLOT(slotDisconnected()),Qt::AutoConnection);
connect(this, SIGNAL(readyRead()), SLOT(slotReadyRead()),Qt::AutoConnection);
connect(this, SIGNAL(error(QAbstractSocket::SocketError)), this,SLOT(slotError(QAbstractSocket::SocketError)),Qt::AutoConnection);
connect(this, SIGNAL(stateChanged(QAbstractSocket::SocketState)),this, SLOT(slotStateChanged(QAbstractSocket::SocketState)),Qt::AutoConnection);
 

и вот эти в отдельном потоке работают нормально
Код
C++ (Qt)
connect(this, SIGNAL(connected()), SLOT(slotConnected()),Qt::AutoConnection);
connect(this, SIGNAL(disconnected()), SLOT(slotDisconnected()),Qt::AutoConnection);
connect(this, SIGNAL(readyRead()), SLOT(slotReadyRead()),Qt::AutoConnection);
 
а вот эти не желают
Код
C++ (Qt)
connect(this, SIGNAL(error(QAbstractSocket::SocketError)), this,SLOT(slotError(QAbstractSocket::SocketError)),Qt::AutoConnection);
connect(this, SIGNAL(stateChanged(QAbstractSocket::SocketState)),this, SLOT(slotStateChanged(QAbstractSocket::SocketState)),Qt::AutoConnection);
 

А в основном потоке нормально отрабатывают все
« Последнее редактирование: Январь 11, 2017, 14:51 от stix357 » Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #34 : Январь 11, 2017, 14:40 »

> Не, к сожалению низя, тогда не успевает очередной пакет получить и нагло из цикла выходит на проверке в начале цикла

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

Как пример, ты ждешь строку. Допустим, строка - это последовательность символов, заканчивающаяся переводом строки. На readyRead ты вычитываешь все, что есть из сокета и ищешь перенос строки - если он есть, обрабатываешь строку, если нету, ждешь дальше. На следующий readyRead ты дочитываешь в буфер все, что пришло и опять производишь поиск.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
stix357
Гость
« Ответ #35 : Январь 11, 2017, 15:01 »

> Не, к сожалению низя, тогда не успевает очередной пакет получить и нагло из цикла выходит на проверке в начале цикла

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

Как пример, ты ждешь строку. Допустим, строка - это последовательность символов, заканчивающаяся переводом строки. На readyRead ты вычитываешь все, что есть из сокета и ищешь перенос строки - если он есть, обрабатываешь строку, если нету, ждешь дальше. На следующий readyRead ты дочитываешь в буфер все, что пришло и опять производишь поиск.
Не, в моем случае этот фокус не пройдет. Я уже пробовал. Тогда радимодуль начинает дурить и вешается. Летит поток байт, и только в самом конце признак окончания передачи.
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #36 : Январь 11, 2017, 15:14 »

Ты что-то делаешь не так. Улыбающийся
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #37 : Январь 11, 2017, 15:14 »

Попробуй выводить в консоль в hex то, что тебе приходит и проанализируй вручную.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
stix357
Гость
« Ответ #38 : Январь 11, 2017, 17:48 »

Попробуй выводить в консоль в hex то, что тебе приходит и проанализируй вручную.
Это про передачу данных от контроллера?
Да я так знаю, что там летит Улыбающийся
Сначала заголовок 17 байт в символах , потом цепочка байтов летит от 00 до FF на канал, затем символьный хвост завершения 19 байт.
Просто по связке:
Код
C++ (Qt)
connect(m_pTcpSocket, SIGNAL(readyRead()), SLOT(slotReadyRead()));
slotReadyRead - не вызывается второй раз, если убрать из цикла
waitForReadyRead(700);//время ожидания очередного пакета
Не успевает радиомодуль контроллера кинуть очередной пакет.
А радиомудуль гонит пакетами в 738 и второй  281 байт.
А у меня клиент смотрит, в цикле, что пусто:
bytesAvailable=m_pTcpSocket->bytesAvailable();
И вылетает из цикла. Убегаем на конец slotReadyRead и усе.
Радиомодуль долбится, ко мне, как клиенту. Но SIGNAL(readyRead()) не срабатывает.
У него (радиомодуля) буфер переполняется (2048 байт) и все, он уходит в аут.
Поэтому я заставляю подождать очередной порции - waitForReadyRead(700)
« Последнее редактирование: Январь 11, 2017, 18:05 от stix357 » Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3258


Просмотр профиля
« Ответ #39 : Январь 11, 2017, 18:01 »

Радиомодуль долбится, ко мне, как клиенту. Но SIGNAL(readyRead()) не срабатывает.

Какая-то хрень, оно должно попадать в буфер принимающей ОС.
Записан
stix357
Гость
« Ответ #40 : Январь 11, 2017, 18:07 »

Радиомодуль долбится, ко мне, как клиенту. Но SIGNAL(readyRead()) не срабатывает.

Какая-то хрень, оно должно попадать в буфер принимающей ОС.
А толку-то? если клиент забил на прием?
Размер изначального пакета неизвестен. Клиент считает, что принял все.
И получаю я RST/ACK
« Последнее редактирование: Январь 11, 2017, 18:12 от stix357 » Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #41 : Январь 11, 2017, 18:16 »

А толку-то? если клиент забил на прием?
Размер изначального пакета неизвестен. Клиент считает, что принял все.
И получаю я RST/ACK
Вот вам и говорят, что у вас сделано неправильно.
Записан
stix357
Гость
« Ответ #42 : Январь 12, 2017, 07:48 »

А толку-то? если клиент забил на прием?
Размер изначального пакета неизвестен. Клиент считает, что принял все.
И получаю я RST/ACK
Вот вам и говорят, что у вас сделано неправильно.
Возможно и так.
Если есть желание - посмотрите, где я ошибся.
https://drive.google.com/file/d/0Bxq5cvEHXCjyVDA3ZVdyXzR4RGM/view?usp=sharing
Прототип клиента
Если убрать из кода:
Код
C++ (Qt)
m_pTcpSocket->waitForReadyRead(550);//время ожидания очередного пакета в  мс
То все, .... получаю только первый пакет. Скриншот ниже. Клиент (192.168.1.12) говорит - усе я принял, больше не надо.
Цитировать
7   4.767455000   192.168.1.12   192.168.1.200   TCP   54   triquest-lm > 32000 [FIN, ACK] Seq=10 Ack=731 Win=65535 Len=0
и отстань от меня сервер
Цитировать
9   4.769592000   192.168.1.12   192.168.1.200   TCP   54   triquest-lm > 32000 [RST, ACK] Seq=11 Ack=1020 Win=0 Len=0
Цитировать
09:57:00.890 ConnectToServer
09:57:00.906 Connected
Delay connect: 16 ms
09:57:04.468 Send +WIND:82:
09:57:04.640 bytesAvailable 730
09:57:04.640 Begin +WIND:83:01:06:03
09:57:04.640 bytesAvailable 0 Пусто
Delay no Data: 172 ms
09:57:04.640 Total Expected: 18034
09:57:04.640 Total Recive: 730
09:57:04.640 Lost: 17304
При включенном ожидании:
Цитировать
Log out
10:19:58.609 ConnectToServer
10:19:58.625 Connected
Delay connect: 16 ms
10:20:01.703 Send +WIND:82:
10:20:01.953 bytesAvailable 730
10:20:01.953 Begin +WIND:83:01:06:03
10:20:02.125 bytesAvailable 730
10:20:02.125 bytesAvailable 578
10:20:02.296 bytesAvailable 730
10:20:02.468 bytesAvailable 730
10:20:02.468 bytesAvailable 578
10:20:02.640 bytesAvailable 730
10:20:02.812 bytesAvailable 289
10:20:02.812 bytesAvailable 730
10:20:02.812 bytesAvailable 289
10:20:02.968 bytesAvailable 730
10:20:02.968 bytesAvailable 289
10:20:03.140 bytesAvailable 730
10:20:03.312 bytesAvailable 730
10:20:03.312 bytesAvailable 578
10:20:03.484 bytesAvailable 730
10:20:03.687 bytesAvailable 289
10:20:03.687 bytesAvailable 730
10:20:03.687 bytesAvailable 289
10:20:03.828 bytesAvailable 730
10:20:03.828 bytesAvailable 289
10:20:04.000 bytesAvailable 730
10:20:04.000 bytesAvailable 289
10:20:04.156 bytesAvailable 730
10:20:04.328 bytesAvailable 730
10:20:04.328 bytesAvailable 578
10:20:04.500 bytesAvailable 730
10:20:04.671 bytesAvailable 289
10:20:04.671 bytesAvailable 730
10:20:04.671 bytesAvailable 289
10:20:04.890 bytesAvailable 711
10:20:04.890 End +WIND:85:00000000
10:20:04.890 Total Expected: 18034
10:20:04.890 Total Recive: 18034
10:20:04.890 Lost: 0
« Последнее редактирование: Январь 12, 2017, 08:37 от stix357 » Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #43 : Январь 12, 2017, 10:08 »

Код
C++ (Qt)
class TCPClient : ...
{
   ...
private:
   QByteArray m_buffer;
};
 
// Слот обработки сигнала readyRead()
void TCPClient::onReadData()
{
   m_buffer += readAll();
 
   // Мы все вычитываем в буфер m_buffer
   // Здесь мы может проверить находится ли в буфере полный пакет данных для обработки, если да - обрабатываем его и выкусываем из буфера
   // Если в буфере осталась только часть пакета, то просто выходим и ждем следующую порцию данных
}
 

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

P.S. даже можно прием и разбор пакетов производить в разных местах.
« Последнее редактирование: Январь 12, 2017, 10:10 от Old » Записан
stix357
Гость
« Ответ #44 : Январь 12, 2017, 10:12 »

Пакет по сети может не прийти полностью или могут прийти сразу несколько пакетов, и все это нужно полноценно разбирать.
Пришла только часть пакета - положили ее в буфер и ушли ждать новую порцию данных.
А как в ожидание уйти?
Пришли несколько пакетов сразу - обработали их все и если остался не полный пакет, то оставили его в буфере и ушли ждать новую порцию данных.
P.S. даже можно прием и разбор пакетов производить в разных местах.
Мне изначально неизвестен размер пакета.
Цитировать
Передаваемые данные с сервера АЦП начинаются с признака начала передачи
строка +WIN:83:XX:XX:XX, затем без отрыва идут данные сэмплами по байту в HEX формате на канал (значение по каналу от 00 до FF), завершает передачу строка ответа о подтверждении завершения измерений +WIND:85:ХХХХХХХХ


А readAll(); это что?
« Последнее редактирование: Январь 12, 2017, 10:44 от stix357 » Записан
Страниц: 1 2 [3] 4   Вверх
  Печать  
 
Перейти в:  


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