Название: QTcpSocket и QThread Отправлено: Harlon от Июнь 05, 2018, 11:07 Не без помощи хороших людей с этого форума, я написал сервер микроконтроллера и клиент на QT для Windows.
Описание сервера: сервер написан на "C" с использованием стэка LWIP, на него поступает запрос, он формирует массив int из 2048 значений и отправляет его на клиент. Описание клиента: клиент написан на QT с использованием QTcpSocket, а делает он следующее: принимает массив от сервера, загоняет его в QVector <int>, записывает данные из QVector в файл и ещё с использованием QtCharts отрисовывает график полученных значений. Всё это делается нажатием на кнопку, которая генерирует запрос на сервер (пакует в QTcpSocket текст запроса и отправляет на сервер.) И всё работает замечательно, но в клиенте теперь нужно сделать следующее: Я должен добавить кнопку (предположим "Старт") и должен начать генерировать запросы на сервер и получать на клиенте с отрисовкой(но тут допустим можно и не каждый массив отрисовывать, а каждый 10, так как за секунду я должен получать 600 таких массивов) и записью в файл, от него ответы пока не нажму кнопку (предположим "Стоп"). Вопрос: можете ли вы подсказать в какую сторону копать, всё таки написать отдельный класс для такой реализации с использованием отдельного соккета и использовать отдельный поток, возможно даже 2 (для отправки запроса и обработки данных) или же можно обойтись и основным потоком используя ещё что-то? Название: Re: QTcpSocket и QThread Отправлено: vic57 от Июнь 05, 2018, 14:56 а зачем тут лишние потоки? пока ты не получишь ответ - нечего рисовать. я когда-то делал имитатор РЛС по схеме клиент - сервер, там по кнопке Старт включался таймер, по таймеру шли запросы и по получению ответа шла отрисовка.
посмотри Fortune client/server http://doc.crossplatform.ru/qt/4.5.0/qtnetwork.html#using-tcp-with-qtcpsocket-and-qtcpserver Название: Re: QTcpSocket и QThread Отправлено: Harlon от Июнь 05, 2018, 16:04 То есть QTcpSoket::write() и redyread() создают отдельные потоки, и там обрабатывают всю инфу, не вешая GUI?
Название: Re: QTcpSocket и QThread Отправлено: Пантер от Июнь 05, 2018, 16:21 Там нет потоков, это асинхронная работа.
Название: Re: QTcpSocket и QThread Отправлено: Harlon от Июнь 05, 2018, 16:52 Всё осознал неправильность своей фразы. Но непонимание осталось. Я отправляю запрос примерно так:
Код
тут я 1 раз нажимаю кнопку посылаю запрос и в redyread() я получаю 2048 значений, тут же их обрабатываю и рисую. Теперь я перепишу реализацию отправки, что бы кнопка при нажатии запускала таймер и по таймеру отправляла запрос, другой кнопкой я буду останавливать таймер, а redyread() не вешая основного потока будет это обрабатывать? Название: Re: QTcpSocket и QThread Отправлено: vic57 от Июнь 05, 2018, 18:06 readyRead - это сигнал, по его приходу выполняется какой-то код(слот)
Название: Re: QTcpSocket и QThread Отправлено: Harlon от Июнь 05, 2018, 18:48 Извиняюсь затупил... В сокете sockRead() выполняется код. А так как он находится в классе MainWindow, он будет вешать главный поток. + Ещё QChart в GraphicsView виджете работает, тут вообще всё повиснет...
Название: Re: QTcpSocket и QThread Отправлено: vic57 от Июнь 05, 2018, 21:00 Извиняюсь затупил... В сокете sockRead() выполняется код. А так как он находится в классе MainWindow, он будет вешать главный поток. + Ещё QChart в GraphicsView виджете работает, тут вообще всё повиснет... с чего это вдруг? имхо ты не понимаешь как QApplication работаетhttp://doc.crossplatform.ru/qt/4.7.x/qapplication.html#details Название: Re: QTcpSocket и QThread Отправлено: Harlon от Июнь 06, 2018, 01:41 Всё разобрался, но есть проблема ещё одна, щас всё отрисовывается и принимается, но если скорость таймера повышаю, до 1.6 мс, то есть я должен буду принимать по 600 массивов по 8кб = 4.8 МБ/с, у меня начинают данные крошиться и значения из массива превращаются в хрен пойми что...
Код
Даже если убрать отрисовку у меня всё равно значения разваливает... Название: Re: QTcpSocket и QThread Отправлено: vic57 от Июнь 06, 2018, 10:36 1. надо читать буфер, чтобы его очистить
Цитировать if (bav < 8192 ) { stream->readAll();//clean buffer return; } Название: Re: QTcpSocket и QThread Отправлено: Harlon от Июнь 06, 2018, 20:29 Не спасло, если я помещаю socket->readAll() в условие, как вы написали, я начинаю терять большую часть данных ибо она стирается ещё раньше чем DataStream успевает их передать в массив. Я поставил очистку буфера сразу после того, как DataStream отработает, и на скорости 10-20 это спасает, но периодически всё равно попадается неверный массив(даже если слот не нагружать отрисовкой).
Вот как примерно выглядит нормальный массив: QVector(502, -1766, -1285, 1130, 1167, 1350, -1212, 1115, 296, 1609, 829, -1732, -124, 1152, 772, 1971, 1537, 7, 474, -220, 1180, 1330, 715, 1081, 731, -74, 1158, 1421, 310, -1916, 1302, -268, -551, 1794, -780, -23, -1937, -958, -941, 1581, 493, -1216, -1038, -690, -400, 1712, -832, 940, 1380, 1215, 233, -1627, 205, -1695, -540, 756, -745, 1174, 683, -1545, 1059, 8, 1946, 367, -1003, 1289, -1398, 73, -429, 656, 1401, 1678, 1325, -1726, 758, 1028, -887, -1181, -1539, 1589, -1623, 633, -1881, -1121, 1514, -41, -801, -635, 1177, 785, 1276, 418, 220, -1814, 341, 317, 844, -1213, 1617, 1185, 836, -1099, -1526, 444, -272, -1424, -229, -1151, 960, 536, 1231, -136, -247, -955, 1857, -1472, 1612, -1524, -1233, 1262, 544, 1986, 135, -62, 1170, -749, 486, 585, -246, 1004, 1643, -1297, -447, -1658, 1771, -621, -134,... А вот так выглядит массив, который разрушился: QVector(1936748367, 0, 73364037, -101318656, 5701631, 24248320, -28246016, -17039361, -25624577, -72876033, -15204353, 42401791, -98697216, 25231359, 61079552, -24051712, -128188417, 33816575, -64159744, -63373313, -49610753, 105447423, -108331008, 104333311, -77463552, 116916223, 36569088, 2686976, 40960000, 29163520, -22478848, 15269887, 66650112, -37552128, 44105727, 50200576, 40632320, 2686976, -3080192, -8388609, 75431935, 18153472, -7274496, -52166657, -12845057, -125370369, -69337089, -28180481, -43122689, 92930047, -73465856, -111280129, 104529919, -34471936, 69533695, -103088128, 38535167, ... Может есть мысли по чему на быстрой скорости так разрушается массив? Название: Re: QTcpSocket и QThread Отправлено: RedDog от Июнь 06, 2018, 20:51 Почему бы не подписаться на readyRead() сокета, в нем вычитывать все что есть в сокете, и этот вычитанный кусок отправлять наверх, где отдельная логика его склеит/разрежет на нужное кол-во байт?
Название: Re: QTcpSocket и QThread Отправлено: vic57 от Июнь 06, 2018, 21:04 Может есть мысли по чему на быстрой скорости так разрушается массив? я бы сделал краш тест сети чисто на С без QtНазвание: Re: QTcpSocket и QThread Отправлено: Harlon от Июнь 06, 2018, 21:07 Дело то в том, что я понимаю если бы я по 30 мегабайт массивы разбирал, а у меня тут максимум при таком таймере максимум 1.6 МБ/с.
Это код отправки массива с сервера (эмуляция): Код
Вот так я принимаю данные: Код
Но даже убирая при таком варианте отрисовку, всё равно массив рушится... На 2 разных устройствах пробовали и с реальным сигналом, всё равно рушится всё и напрямую подрубал к компу, у меня в интернет скорость выше в 2 раза чем в локалке с кабелем 1 метр. (имею ввиду при обмене через свою программу) Название: Re: QTcpSocket и QThread Отправлено: Old от Июнь 06, 2018, 21:15 Вы вычитываете из сокета массив, а потом делаете readAll? Вычитаваете остальные пришедшие данные и теряете их?
Название: Re: QTcpSocket и QThread Отправлено: Harlon от Июнь 06, 2018, 21:19 Нет это просто уже от безысходности я начал пихать его куда попало...
Название: Re: QTcpSocket и QThread Отправлено: vic57 от Июнь 06, 2018, 21:20 ну а где у тебя маркер начала/конца блока например?
я в свое время делал так- 1.маркер начала блока - 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xd - 8 байт 2.циклический номер блока - 0x0 - 0xff - 2 байта 3.длина блока данных - 0x0 - 0xffff - 4 байта 4.блок данных 5. контрольная сумма(опционально) - 4 байта у тебя нет внутренней структуры данных, поэтому ты и не можешь отловить ошибки Название: Re: QTcpSocket и QThread Отправлено: Old от Июнь 06, 2018, 21:23 Нет это просто уже от безысходности я начал пихать его куда попало... Это кусок кода из слота обработки сигнала readyRead? Что делается в отрисовке. Покажите весь слот.Название: Re: QTcpSocket и QThread Отправлено: Harlon от Июнь 06, 2018, 21:29 Код
Да леший с этой отрисовкой, мне главное целостность данных и скорость передачи (отрисовка дело третье, её можно вообще каждый 10 или 15 раз отрисовывать) Название: Re: QTcpSocket и QThread Отправлено: vic57 от Июнь 06, 2018, 22:10 http://www.prog.org.ru/index.php?topic=32063.msg236503#msg236503
делай как здесь, буфер сокета надо очищать, он может тупо переполниться Название: Re: QTcpSocket и QThread Отправлено: Harlon от Июнь 07, 2018, 08:25 А если я в начало буфера допустим строку, допустим char *next_block = "accept"; (6байт)
Код
А на клиенте: Код
И ещё сразу спрошу: что бы запихнуть в несколько потоков отправку сообщения серверу, я предполагаю это лучше делать через отдельный класс унаследованный от QObject, в котором я создам слот Run(), в котором будет выполнятся отправка, НО я не могу представить как передавать туда команду socket->write() из MainWindow... В общем опять каша, подскажите как решить это или тут надо новый класс для сокета делать? Всё с потоками вроде разобрался, осталось только принять нормально. Название: Re: QTcpSocket и QThread Отправлено: vic57 от Июнь 07, 2018, 18:16 у тебя однопоточный сервак, зачем тебе многопоточный клиент?
вангую что железка работает на прерываниях и ты не дожидаешься окончания передачи пакета и даешь команду на передачу нового пакета посмотри рабочий пример Название: Re: QTcpSocket и QThread Отправлено: Harlon от Июнь 07, 2018, 18:17 https://evileg.com/ru/post/152/
Вот так возможно реализовать поток? Передавая свой сокет по ссылке? Да там есть прерывания... Блин ты прав, у меня стакается запрос в железке, я допустим посылаю туда char s = 'A'; а получаю строку 'AA' и вот и косячина... Первый раз просто с железкой работаю, неопытный, даже и не предполагал, что так может быть... Пример посмотрел спасибо! vic57 подскажите пожалуйста, каким образом можно избежать данной проблемы, хотя бы куда капнуть? Название: Re: QTcpSocket и QThread Отправлено: vic57 от Июнь 08, 2018, 02:00 посылать запрос на следующий пакет только после приема и проверки текущего.
вообще если тебе надо гнать цифру тут tcp и не нужен особо, я на udp делал, проще получается. а тестировал массивом - гнал массив например 40000 байт, его зеркалил обратно и сравнивал только я 2 сокета использовал - прием и передачя Название: Re: QTcpSocket и QThread Отправлено: Harlon от Июнь 08, 2018, 07:58 Нашел в документации:
Код
The TcpFastTmrFlag and TcpSlowTmrFlag are required for TCP TX handling and are set in the Timer handler for every 250 ms and 500 ms, respectively. The function of the application loop is to receive packets constantly (xemacif_input), then pass them on to lwIP. Before entering this loop, the echo server sets up certain callbacks:... Получается я начинаю сервер бомбить запросами раз в 5мс, а он на 250 - 500 мс блокируется, неудивительно, что я так обламывался. Название: Re: QTcpSocket и QThread Отправлено: vic57 от Июнь 08, 2018, 14:07 ну это врят ли, скорее через 250-500 мс чего-то там подстраивается. не знаю на чем ты пишешь, я на линухе делал замеры как-то - время реакции ядра на приход данных (poll) - 5 мс. так что обломись сразу :o реально не менее 10мс депать. быстрее будут тока сборки типа роутеров, это их основная функция.
http://static1.ozone.ru/multimedia/book_file/1003560303.pdf в этой книге про сокеты неплохо написано Название: Re: QTcpSocket и QThread Отправлено: Harlon от Июнь 08, 2018, 20:33 У меня не Linux, у меня микропроцессорная система на кристалле, без ОС. http://www.myirtech.com/list.asp?id=565 вот такая штука.
Название: Re: QTcpSocket и QThread Отправлено: vic57 от Июнь 08, 2018, 21:45 там arm-linux только IDE под WIN
я имею в виду клиента на чем пишешь Название: Re: QTcpSocket и QThread Отправлено: Harlon от Июнь 08, 2018, 23:12 Клиент на QT под виндой, на плате голо, как на коленке. Другая плата разогналась до 200! Победа, тормозила рисовалка. Теперь другая беда, как обойти этот таймер?
Код
Название: Re: QTcpSocket и QThread Отправлено: vic57 от Июнь 08, 2018, 23:46 как то ты странно пишешь
Код делай краш тест на Си, без таймеров Код
Название: Re: QTcpSocket и QThread Отправлено: Harlon от Июнь 09, 2018, 11:06 Этот код я так понимаю только под линуксом работает?
Название: Re: QTcpSocket и QThread Отправлено: vic57 от Июнь 09, 2018, 12:07 ну да, под винду надо WinSock подключать
https://studfiles.net/preview/1551127/page:2/ Название: Re: QTcpSocket и QThread Отправлено: Harlon от Июнь 09, 2018, 15:09 А в QT так сделать не получится?
Мне просто надо сейчас из моего приложения отправлять минимум 600 запросов, железку допишут люди знающие, что делают, главное, что бы клиент выжимал, как можно больше... Я щас пробую сделать несколько потоков для отправки, но это мне во-первых не очень удается, а во-вторых я не уверен, что я правильный подход использую. Название: Re: QTcpSocket и QThread Отправлено: vic57 от Июнь 09, 2018, 21:21 потоки не помогут - проволока одна
как вариант создать отдельный тред, который будет заниматься только запросом - ответом и писать в общий буфер, а в основном треде из буфера читать и рисовать. тут можно поделить задачу по ядрам процессора. типа так http://www.bogotobogo.com/Qt/Qt5_QTcpServer_QThreadPool_Multithreaded_Client_Server.php или как в network/Loopback Example Название: Re: QTcpSocket и QThread Отправлено: Harlon от Июнь 10, 2018, 12:04 Код
А вот такая штука сработает? Название: Re: QTcpSocket и QThread Отправлено: vic57 от Июнь 10, 2018, 14:19 а звчем это? в Loopback Example у меня на локалхосте скорость 200 МВ/с, если с внешним сервером не поднимается - канал передачи данных тормозит
Название: Re: QTcpSocket и QThread Отправлено: Harlon от Июнь 10, 2018, 15:35 Попробую адаптировать, чет у меня от этого примера глаза разбегаются, они бы хоть комментировали его... ;D
Посмотрел, попробовал, но только не понял, как это решает мою проблему отправки моих запросов со скоростью 1 раз в 1 - 1.6 мс., Да передает он тут 50 мегабайт, а фишка-то в чем. Походу я опять не догоняю, что-то... Решил попробовать qWait из QTest: Код
Всем спасибо за то, что меня терпели, как и сказал vic57 из-за прерываний у меня не получится с такой скоростью опрашивать железку. И тут недавно я узнал, что такое кольцевой буфер и моя проблема почти улетучилась(просто пока я разбираюсь, как это будет работать у меня). В общем всем ОГРОМНОЕ ЧЕЛОВЕЧЕСКОЕ СПАСИБО. Название: Re: QTcpSocket и QThread Отправлено: vic57 от Июнь 13, 2018, 18:40 интересно что получилось с буфером, что-то я не знаю такой вариант ???
Название: Re: QTcpSocket и QThread Отправлено: Harlon от Июнь 14, 2018, 08:02 А сейчас расскажу, чем вообще дело кончилось. И кольцевой буфер не понадобился, хотя для камеры и потока видео его желательно бы иметь, но у меня другая задача была. В общем мне помог добрый человек увеличить snd_buffer у LWIP до 64КБ и тут, как понеслось я переписал реализацию в отдельную функцию отправки, т.е. я сейчас посылаю один запрос и врубается поток, да такой дикий, что у меня софтина верхняя виснет. Далее мы дэлэем подкрутили скорость опроса до нужных нам 600 массивов/с. Программа на ура пережевала это всё. Далее до 800, тоже вроде нормально. Но из-за отрисовки бывало верхняя прога висла, на ней надо было сделать "Disconnect", потом опять подключиться и она продолжала работать.(Фиг знает почему она так виснет, я думаю надо всё таки как-то рисовалку в поток другой выслать). Ну я вырубил отрисовку и оп ля 1кГц, 1000 массивов в секунду, жуются. Сейчас думаю над верхним софтом, моим, как бы его разгрузить...
|