|
STM32F4+lwip медленно работает. |
|
|
|
Nov 8 2016, 10:31
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(Oleg_IT @ Nov 8 2016, 13:23)  Еслиб это было так, lwip, у меня, ни чего не копит Интересно, на основании чего вы сделали этот вывод. Цитата(Oleg_IT @ Nov 8 2016, 13:23)  если посылать чаще, то пакеты теряются, подпрограмма tcp_write выдаёт ошибку памяти. Если посылать 100500 раз в секунду, точно будут ошибки - буферы не резиновые. Короче, что там у вас в коде творится - только вам ведомо. Кода мы не видели. Телепаты в отпуске  Цитата(Oleg_IT @ Oct 31 2016, 09:01)  очередную порцию передаю по приходу ответа с принимающей стороны А вот это зачем? Есть же у TCP механизм подтверждений, никакие "ответы" не требуются.
|
|
|
|
|
Nov 8 2016, 19:27
|
практикующий тех. волшебник
    
Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417

|
Цитата(Oleg_IT @ Nov 8 2016, 12:48)  ... Фрагмент кода приёмника Код void MainWindow::slotReadyRead() { if (m_pTcpSocket == NULL || m_pTcpSocket->isOpen() == false) return;
slotSendToServer();
QByteArray dAll; dAll.clear(); dAll = m_pTcpSocket->readAll(); SizeAll = dAll.count(); if (AddData(dAll.data(),SizeAll,(uint8_t*)m_Data.Data) == true) WidgetMain->DrawGr(); } ... Подкорректируйте меня если я обшибаюсь... Вы очищаете массив(закос под кути или порт кутишный). Считываете всё что пришло в ку-байт-эррэй. получаете кол-во принятых байт. и далее передаёте на обработку.... Т.е. для этого кода, будет ликвиден и один байт, и два, и 100, и килобайт. Т.е. если например произошёл затор в сети, и ваши данные на IP уровне безбожно режутся хопами, вы можете получить очень и очень разные и замысловатые длины полезных данных. Представляйте себе трубу. С одной стороны в которую заливают данные, с другой вы эти данные последовательно выгребаете. Но если Вам нужна квантованность - то увы и ах, это Ваша личная забота. И то что Вы будете получать в одном тихом локальном сегменте сети апсолютно не даст гарантии того, что при ударной нагрузке либо потерях в сети Ваш код будет устойчиво работать. Обратите внимание на реализацию приёмников в грамотных кодах серваков - там кол-во байт которое необходимо принять передаётся в подпрограмму приёма. И подпрограмма действует по принципу либо всё либо ошибка. Длины данных обычно передают в хедере фиксированной длины. т.е. Ваш приёмник (как один из вариантов) должен быть реализован как приём фиксированной длины хедера, далее взятие из этого хедера длины данных, подготовка приёмного буффера, и собственно приём данных пришедшей из хидера. удачи вам (круглый) ЗЫ Есть ещё настройки TCP уровня по задержке перед передачей, но там задержки(по дефолту - не более нескольких мс). Т.е. если у Вас глюкало на секунды-минуты - это явно хромает консерватория... ЗЫ ЗЫ Ваш код приёмника (я сначала подумал что под армом пишете, но от этого рояль не меняется) может быть типа такого Код void CTcpClient::_slotAnswera() { if (m_baHeader.size() == 0) { if (m_pTcpSocket->bytesAvailable() < sizeof(HRBusinessLogic::Tools::SDataHeader)) return; // m_baHeader = m_pTcpSocket->read(sizeof(HRBusinessLogic::Tools::SDataHeader)); } // const HRBusinessLogic::Tools::SDataHeader* pReceiveData = reinterpret_cast<const HRBusinessLogic::Tools::SDataHeader*>(m_baHeader.constData()); // if (m_pTcpSocket->bytesAvailable() < pReceiveData->m_unSize) return; // QByteArray data = m_pTcpSocket->read(pReceiveData->m_unSize); data.push_front(m_baHeader); m_baHeader.clear(); emit eventProcessingData(data); }
Сообщение отредактировал kolobok0 - Nov 8 2016, 19:50
|
|
|
|
|
Nov 9 2016, 05:49
|
Знающий
   
Группа: Свой
Сообщений: 922
Регистрация: 3-06-05
Из: Москва
Пользователь №: 5 709

|
Буфер конечно не резиновый, но и о скорости 100500 я не говорю, первый же вызов tcp_write не дождавшись ответа, вызывает ошибку памяти и этот посланный пакет теряется. Из этого и сделал вывод, что «lwip, у меня, ни чего не копит» и на приёмной стороне номеров этих пакетов не получаю. По Qt. Цитата Вы очищаете массив(закос под кути или порт кутишный). Считываете всё что пришло в ку-байт-эррэй. получаете кол-во принятых байт. и далее передаёте на обработку.... Можно и не очищать. Да всё так. В обработчике AddData у меня стоит сборщик кусков, в пакете синхронизатор включён, а сам пакет постоянной длины, сделал этот код сам, проверено, работает. Пришлось сделать этот код, кода начал получать два пакета одинаковой длины в двух пакетах разной длины, я это уже отмечал. Сделал на PC имитатор стороны ARM, скорости держит несколько килогерц, специально вводил разбиение пакетов, связка работает стабильно. Цитата погуглите по ключевым словами "LwIP delayed ack" и "LwIP nagle algorithm", возможно найдете что-то полезное. Смотрел, информации по этим темам не много, пока чего-то туплю
|
|
|
|
|
Nov 9 2016, 06:53
|
Гуру
     
Группа: Свой
Сообщений: 2 223
Регистрация: 3-03-06
Из: Tomsk
Пользователь №: 14 925

|
Цитата(Oleg_IT @ Nov 9 2016, 12:49)  Буфер конечно не резиновый, но и о скорости 100500 я не говорю, первый же вызов tcp_write не дождавшись ответа, вызывает ошибку памяти и этот посланный пакет теряется. Из этого и сделал вывод, что «lwip, у меня, ни чего не копит» и на приёмной стороне номеров этих пакетов не получаю. Копит-копит, куда же он денется, после tcp_output он должен дождаться подтверждения от принимающей стороны и только тогда очистит свой буфер. А если не получит, то попытается еще раз отправить, потому что TCP гарантирует доставку. Например у меня прибор в режиме ожидания вообще 2 байта посылает в каждом пакете раз в секунду, и я отлично вижу эти пакеты по 2 байта.
|
|
|
|
|
Nov 9 2016, 10:39
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(Oleg_IT @ Nov 9 2016, 13:06)  Не понимаю тогда куда мне девать ошибку памяти? Если я два раза подряд отправляю пакеты, то второй раз выдаёт ошибку памяти. Не пойму пока куда смотреть чего проверять. Самое простое - включить статистику lwip. Там сразу видно, сколько буферов занято, сколько осталось. Цитата(Oleg_IT @ Nov 9 2016, 13:06)  Размерв буферов максимальные из рекомендации поставил. Там в настройках побольше степеней свободы, чем просто "размеры буферов максимальные". Буферы бывают разные, у них есть размер и кол-во. Также есть куча. Короче, без поллитры не разберёшься. Включайте статистику.
|
|
|
|
|
Nov 9 2016, 19:02
|
практикующий тех. волшебник
    
Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417

|
Цитата(Oleg_IT @ Nov 9 2016, 08:49)  ..В обработчике AddData у меня стоит сборщик кусков,...Пришлось сделать этот код, кода начал получать... если Вы уверены в сборке - это конечно же хорошо. то что Вы дублируете два-раза-два-раза кэшширование и сборку полезных данных - ну значит Вам так проще осязать. осталось обратиться к барабашке  постарайтесь выкинуть всю обработку на приёме и сделать тупую отправку в сеть. если есть сетевой анализатор - то по любому адресу кроме 127.0.0.1 после этого посмотрите скорость и задержки. если их нет = проблемы в консерватории. ведь судя по трафику арм выдаёт запрос штатно, писюк выдаёт тайм-аут. собственно два вектора 1) почему писюк завис(не выдал подтверждения) 2) почему арм не пытается пропихнуть далее ситуацию(ретрансмит) обратите внимание на временной лаг ответа со стороны писюка и со стороны арма. со стороны арма - около 250 мс (что собственно слишком медленно, но не смертельно) со стороны писюка в 1000 раз быстрее. т.е. на писюке имеем запас по скорострельности более чем в 1000 раз. посему зависон со стороны арма(нет ретрансмишена) - это фигня по сравнению с зависоном со стороны писюка (он уже мог сотню раз принять решение). значит не может. думаю рыть надо в сторону писюка. зная не тривиальную обработку сокетов под кути, думаю что истина где то рядом... попытайтесь сделать передачу без вашей логики приёма и сбора пакетов. сразу на передачу. думаю ситуация сдвинется с мёртвой точки. удачи вам (круглый)
Сообщение отредактировал kolobok0 - Nov 9 2016, 19:03
|
|
|
|
|
Nov 10 2016, 04:56
|

Знающий
   
Группа: Свой
Сообщений: 633
Регистрация: 21-05-10
Из: Томск
Пользователь №: 57 423

|
Не надо делать так: Код slotSendToServer();
QByteArray dAll; dAll.clear(); dAll = m_pTcpSocket->readAll(); Необходимо дождаться данных, прежде чем читать: Код slotSendToServer();
if (!m_pTcpSocket->waitForReadyRead()) { qDebug() << "Не дождались ответа"; return; }
QByteArray dAll = m_pTcpSocket->readAll();
--------------------
|
|
|
|
|
Nov 10 2016, 05:14
|
Знающий
   
Группа: Свой
Сообщений: 922
Регистрация: 3-06-05
Из: Москва
Пользователь №: 5 709

|
Цитата(arhiv6 @ Nov 10 2016, 08:56)  Слот slotReadyRead() срабатывает только тогда, когда данные уже готовы, так что ждать тут не чего. kolobok0 спасибо, учту Ваши рекомендации
Сообщение отредактировал IgorKossak - Nov 10 2016, 11:23
Причина редактирования: бездумное цитирование
|
|
|
|
|
Nov 10 2016, 08:44
|
Знающий
   
Группа: Свой
Сообщений: 922
Регистрация: 3-06-05
Из: Москва
Пользователь №: 5 709

|
Цитата(arhiv6 @ Nov 10 2016, 10:04)  Но Вы запись в сокет делаете из этой же функции, когда вызываете функцию slotSendToServer(). И после этого сразу же читаете из сокета данные, не проверяя их готовность. Вот если бы запись проходила в другом месте - вопросов не возникло бы. А так - данные могут теряться. Там же буфера разные на чтение и запись, у меня ни чего не теряется. Всё лишнее с обеих сторон повыкидывал, остался только номер пакета. Кстати, сейчас передаю по 1024 байта, один пакет передал, один пакет принял, так что в сборщике пакетов потребности сейчас нет. Ситуация та же.
|
|
|
|
|
Nov 16 2016, 13:27
|
Знающий
   
Группа: Свой
Сообщений: 922
Регистрация: 3-06-05
Из: Москва
Пользователь №: 5 709

|
Решил я свою проблему. Код отсылки такой Код tcp_nagle_disable(pcb); tcp_write(pcb, Ptr, Size, 0); tcp_output(pcb); Спасибо "Сергей Борщ" и "scifi".
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|