Jump to content

    
Sign in to follow this  
Oleg_IT

STM32F4+lwip медленно работает.

Recommended Posts

Еслиб это было так, lwip, у меня, ни чего не копит

Интересно, на основании чего вы сделали этот вывод.

 

если посылать чаще, то пакеты теряются, подпрограмма tcp_write выдаёт ошибку памяти.

Если посылать 100500 раз в секунду, точно будут ошибки - буферы не резиновые.

 

Короче, что там у вас в коде творится - только вам ведомо. Кода мы не видели. Телепаты в отпуске :laughing:

 

очередную порцию передаю по приходу ответа с принимающей стороны

А вот это зачем? Есть же у TCP механизм подтверждений, никакие "ответы" не требуются.

Share this post


Link to post
Share on other sites
...

Фрагмент кода приёмника

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);
}

Edited by kolobok0

Share this post


Link to post
Share on other sites

Буфер конечно не резиновый, но и о скорости 100500 я не говорю, первый же вызов tcp_write не дождавшись ответа, вызывает ошибку памяти и этот посланный пакет теряется. Из этого и сделал вывод, что «lwip, у меня, ни чего не копит» и на приёмной стороне номеров этих пакетов не получаю.

 

По Qt.

Вы очищаете массив(закос под кути или порт кутишный).

Считываете всё что пришло в ку-байт-эррэй.

получаете кол-во принятых байт.

и далее передаёте на обработку....

Можно и не очищать. Да всё так. В обработчике AddData у меня стоит сборщик кусков, в пакете синхронизатор включён, а сам пакет постоянной длины, сделал этот код сам, проверено, работает. Пришлось сделать этот код, кода начал получать два пакета одинаковой длины в двух пакетах разной длины, я это уже отмечал.

Сделал на PC имитатор стороны ARM, скорости держит несколько килогерц, специально вводил разбиение пакетов, связка работает стабильно.

 

погуглите по ключевым словами "LwIP delayed ack" и "LwIP nagle algorithm", возможно найдете что-то полезное.

Смотрел, информации по этим темам не много, пока чего-то туплю:)

Share this post


Link to post
Share on other sites
Буфер конечно не резиновый, но и о скорости 100500 я не говорю, первый же вызов tcp_write не дождавшись ответа, вызывает ошибку памяти и этот посланный пакет теряется. Из этого и сделал вывод, что «lwip, у меня, ни чего не копит» и на приёмной стороне номеров этих пакетов не получаю.

Копит-копит, куда же он денется, после tcp_output он должен дождаться подтверждения от принимающей стороны и только тогда очистит свой буфер. А если не получит, то попытается еще раз отправить, потому что TCP гарантирует доставку.

Например у меня прибор в режиме ожидания вообще 2 байта посылает в каждом пакете раз в секунду, и я отлично вижу эти пакеты по 2 байта.

Share this post


Link to post
Share on other sites

Я свои байты вижу четыре раза в секунду.

 

Может и копит, этот момент я пока не понимаю. Не понимаю тогда куда мне девать ошибку памяти? Если я два раза подряд отправляю пакеты, то второй раз выдаёт ошибку памяти. Не пойму пока куда смотреть чего проверять. Размерв буферов максимальные из рекомендации поставил.

 

Share this post


Link to post
Share on other sites
Не понимаю тогда куда мне девать ошибку памяти? Если я два раза подряд отправляю пакеты, то второй раз выдаёт ошибку памяти. Не пойму пока куда смотреть чего проверять.

Самое простое - включить статистику lwip. Там сразу видно, сколько буферов занято, сколько осталось.

 

Размерв буферов максимальные из рекомендации поставил.

Там в настройках побольше степеней свободы, чем просто "размеры буферов максимальные". Буферы бывают разные, у них есть размер и кол-во. Также есть куча. Короче, без поллитры не разберёшься. Включайте статистику.

Share this post


Link to post
Share on other sites
Может и копит, этот момент я пока не понимаю. Не понимаю тогда куда мне девать ошибку памяти? Если я два раза подряд отправляю пакеты, то второй раз выдаёт ошибку памяти. Не пойму пока куда смотреть чего проверять. Размерв буферов максимальные из рекомендации поставил.

Выкладывайте свой код и настройки LwIP. Так бесполезно объяснять что у вас не работает.

Share this post


Link to post
Share on other sites
..В обработчике AddData у меня стоит сборщик кусков,...Пришлось сделать этот код, кода начал получать...

 

если Вы уверены в сборке - это конечно же хорошо.

то что Вы дублируете два-раза-два-раза кэшширование и сборку полезных данных - ну значит Вам так проще осязать.

 

осталось обратиться к барабашке :)

 

постарайтесь выкинуть всю обработку на приёме и сделать тупую отправку в сеть. если есть сетевой анализатор - то по любому адресу кроме 127.0.0.1

 

после этого посмотрите скорость и задержки. если их нет = проблемы в консерватории.

 

ведь судя по трафику арм выдаёт запрос штатно, писюк выдаёт тайм-аут. собственно два вектора

1) почему писюк завис(не выдал подтверждения)

2) почему арм не пытается пропихнуть далее ситуацию(ретрансмит)

 

обратите внимание на временной лаг ответа со стороны писюка и со стороны арма.

со стороны арма - около 250 мс (что собственно слишком медленно, но не смертельно)

со стороны писюка в 1000 раз быстрее. т.е. на писюке имеем запас по скорострельности более чем в 1000 раз.

 

посему зависон со стороны арма(нет ретрансмишена) - это фигня по сравнению с зависоном со стороны писюка (он уже мог сотню раз принять решение). значит не может.

 

думаю рыть надо в сторону писюка. зная не тривиальную обработку сокетов под кути, думаю что истина где то рядом...

попытайтесь сделать передачу без вашей логики приёма и сбора пакетов. сразу на передачу. думаю ситуация сдвинется с мёртвой точки.

 

удачи вам

(круглый)

Edited by kolobok0

Share this post


Link to post
Share on other sites

Не надо делать так:

 slotSendToServer();

QByteArray dAll;
dAll.clear();
dAll = m_pTcpSocket->readAll();

Необходимо дождаться данных, прежде чем читать:

 slotSendToServer();

if (!m_pTcpSocket->waitForReadyRead())
{
    qDebug() << "Не дождались ответа";
    return;
}

QByteArray dAll = m_pTcpSocket->readAll();

Share this post


Link to post
Share on other sites

Слот slotReadyRead() срабатывает только тогда, когда данные уже готовы, так что ждать тут не чего.

 

kolobok0 спасибо, учту Ваши рекомендации

Edited by IgorKossak
бездумное цитирование

Share this post


Link to post
Share on other sites

Но Вы запись в сокет делаете из этой же функции, когда вызываете функцию slotSendToServer(). И после этого сразу же читаете из сокета данные, не проверяя их готовность. Вот если бы запись проходила в другом месте - вопросов не возникло бы. А так - данные могут теряться.

Share this post


Link to post
Share on other sites
Но Вы запись в сокет делаете из этой же функции, когда вызываете функцию slotSendToServer(). И после этого сразу же читаете из сокета данные, не проверяя их готовность. Вот если бы запись проходила в другом месте - вопросов не возникло бы. А так - данные могут теряться.

Там же буфера разные на чтение и запись, у меня ни чего не теряется.

 

Всё лишнее с обеих сторон повыкидывал, остался только номер пакета. Кстати, сейчас передаю по 1024 байта, один пакет передал, один пакет принял, так что в сборщике пакетов потребности сейчас нет. Ситуация та же.

Share this post


Link to post
Share on other sites

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

Log.txt

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this