реклама на сайте
подробности

 
 
> lwip: как принимать данные?
H90
сообщение Dec 27 2010, 07:09
Сообщение #1





Группа: Новичок
Сообщений: 6
Регистрация: 27-12-10
Пользователь №: 61 902



Приветствую.
Есть lwip для lm3s9b92 из примера StellarisWare. В примере использован метод GET, требуется реализовать метод POST для передачи файлов. Размер файла значительно превышает размер окна. Как я понимаю, необходимо сделать примерно следующее (метод POST вписал в пример туда же, где обработка GET):
http_recv -> tcp_recved -> декодировать POST -> tcp->write(200 OK)-> [принимать данные.]
[Принимать данные]:
while(не кончился контент)
{http_recv -> tcp_recved -> tcp_write(WHAT?)}
Функция tcp_write(WHAT?) или какая-либо другая должна сообщить уровню ТСР, что можно послать АСК и принять следующую порцию данных.

ЧТО именно нужно посылать функцией tcp_write, чтобы подтвердить принятые данные и начать получать следующие? Пробовал посылать данные нулевой длины - возникает постоянный duplicate ack при анализе wireshark'ом. Если посылать 200 ОК, то рвётся соединение. Если вообще ничего не посылать - ничего не происходит, соединение рвётся по таймауту (т.е.одной tcp_recved) недостаточно. Может, надо использовать не tcp_write, а другую функцию - тогда какую?

Примеров с POST или с приёмом более одного окна я не нашёл. С lwip и сетевыми протоколами ранее не работал.

Прошу подсказать, как надо правильно это делать.

Сообщение отредактировал H90 - Dec 27 2010, 07:12
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
scifi
сообщение Dec 27 2010, 08:52
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(H90 @ Dec 27 2010, 13:09) *
Функция tcp_write(WHAT?) или какая-либо другая должна сообщить уровню ТСР, что можно послать АСК и принять следующую порцию данных.
ЧТО именно нужно посылать функцией tcp_write, чтобы подтвердить принятые данные и начать получать следующие?

Функция tcp_recved() сообщает стеку, что можно посылать ACK и принимать новые данные. Не нужно делать tcp_write().

Цитата(H90 @ Dec 27 2010, 13:09) *
Если вообще ничего не посылать - ничего не происходит, соединение рвётся по таймауту (т.е.одной tcp_recved) недостаточно. Может, надо использовать не tcp_write, а другую функцию - тогда какую?

Из Вашего объяснения я так и не понял, как устроена Ваша программа. Стек lwip требует, чтобы периодически (каждые 250 мс) вызывалась функция tcp_tmr(). Иначе всё застопорится. Ваше "while(не кончился контент)" этому вопиющим образом противоречит. Данные принимает callback-функция по одному кусочку за раз, складывает их куда надо, вызывает tcp_recved() и сразу возвращается. Простой цикл while() в эту схему не вписывается.
Go to the top of the page
 
+Quote Post
H90
сообщение Dec 28 2010, 01:01
Сообщение #3





Группа: Новичок
Сообщений: 6
Регистрация: 27-12-10
Пользователь №: 61 902



Цитата(scifi @ Dec 27 2010, 15:52) *
Из Вашего объяснения я так и не понял, как устроена Ваша программа. Стек lwip требует, чтобы периодически (каждые 250 мс) вызывалась функция tcp_tmr().

Программа устроена так, как устроен пример в StellarisWare, В т.ч. вызывается tcp_tmr, т.к.диагностические сообщения от tcp_slow_tmr выводятся на консоль. В пример добавлен разбор запроса POST, а вместо send_data была попытка посылать что-либо, описанное выше... Это прекрасно работает при приёме файла из одного окна. Параллельно с этим прекрасно работает сайт из примера. Параллельно работает UDP на своём порту. Т.е.структура нормальная. While из моего вопроса означает, что я продолжаю обрабатывать принятые данные в коллбэчной функции http_recv и пытаться выдавать что-то с целью АСК'а, затем делать return до тех пор, пока не истечёт полученная в первом запросе POST длина Content Length.

Плюс "по наитию" сделано то, чего не было в примере - выемка данных из цепочки pbuf'ов:
p = p->next; if(p){..выемка..} else pbuf_free(pbuf0);, где pbuf0 - изначальный pbuf в цепочке. Не знаю, правильно это или нет.

Цитата(scifi @ Dec 27 2010, 15:52) *
Функция tcp_recved() сообщает стеку, что можно посылать ACK и принимать новые данные. Не нужно делать tcp_write().

Да, без tcp_write получилось после переноса tcp_recvd из начала обработки (как было в примере) в конец, после выемки всей цепочки и выдачи по UARTу всех логов. Но duplicate ack всё равно остался: первый посылается tcp_recved, второй посылается после выхода из коллбэчной функции http_recv функцией tcp_input отсюда:
Код
        /* If there were no errors, we try to send something out. */
        if (err == ERR_OK) {
          tcp_output(pcb);

Выглядит это так:
Код
12    2.096778    192.168.66.50    192.168.66.1    TCP    http > 48728 [ACK] Seq=25 Ack=4381 Win=4096 Len=0
13    2.096824    192.168.66.1    192.168.66.50    TCP    [TCP segment of a reassembled PDU]
14    2.096835    192.168.66.1    192.168.66.50    TCP    [TCP segment of a reassembled PDU]
15    2.341158    192.168.66.50    192.168.66.1    TCP    http > 48728 [ACK] Seq=25 Ack=5841 Win=4096 Len=0
16    2.341205    192.168.66.1    192.168.66.50    TCP    [TCP segment of a reassembled PDU]
17    2.523333    192.168.66.50    192.168.66.1    TCP    [TCP Dup ACK 15#1] http > 48728 [ACK] Seq=25 Ack=5841 Win=4096 Len=0
18    3.564769    192.168.66.1    192.168.66.50    TCP    [TCP Retransmission] [TCP segment of a reassembled PDU]

66 1 - компьютер, 66 50 - контроллер.
Такие группы из двух нормальных АСК и одного дубликата идут при приёме всего файла. Сейчас только tcp_recved, tcp_write делается 1 раз в начале для ответа 200 ОК.

Как избавиться от дубликатов, пока не понятно.

А есть ли готовый пример с обработкой POST? Буду благодарен за помощь.

Go to the top of the page
 
+Quote Post
scifi
сообщение Dec 28 2010, 06:16
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(H90 @ Dec 28 2010, 07:01) *
Плюс "по наитию" сделано то, чего не было в примере - выемка данных из цепочки pbuf'ов:
p = p->next; if(p){..выемка..} else pbuf_free(pbuf0);, где pbuf0 - изначальный pbuf в цепочке. Не знаю, правильно это или нет.

Можно подсмотреть в примерах, идущих вместе с lwip. Посмотрите echo.c, функция echo_send():
echo.c
Правда, я подозреваю, что там есть избыточные вещи (автор, наверное, от чего-то перестраховывался). Но всё равно интересно.
Цитата(H90 @ Dec 28 2010, 07:01) *
А есть ли готовый пример с обработкой POST? Буду благодарен за помощь.

Высылаю свой веб-сервер. Но там несколько заморочно. Может быть, будет чем-то полезен.
Прикрепленные файлы
Прикрепленный файл  httpd.txt ( 35.78 килобайт ) Кол-во скачиваний: 156
 
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 31st July 2025 - 21:20
Рейтинг@Mail.ru


Страница сгенерированна за 0.03664 секунд с 7
ELECTRONIX ©2004-2016