Перейти к содержанию

lwIp tcp клиент для STM32

имеется сервер TCP, который на запрос клиента "M\r" отправляет два сообщения:

1. "ОК\r"

2. "какое-то значение\r"

 

имеется отладка stm32f746g-disco и пример "LwIP_TCP_Echo_Client" из набора STM32Cube.

 

работает замечательно, за исключением одного, не принимает сообщение №2.

т.е. после приема первого сообщения соединение закрывается.

 

err_t tcp_echoclient_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{
struct echoclient *es;
err_t ret_err;

LWIP_ASSERT("arg != NULL", arg != NULL);

es = (struct echoclient *)arg;

/* if we receive an empty tcp frame from server => close connection */
if (p == NULL)
{
	/* remote host closed connection */
	es->state = ES_CLOSING;
	if (es->p_tx == NULL)
	{
		/* we're done sending, close connection */
		tcp_echoclient_connection_close(tpcb, es);
	}
	else
	{
		/* send remaining data*/
		tcp_echoclient_send(tpcb, es);
	}
	ret_err = ERR_OK;
}
/* else : a non empty frame was received from echo server but for some reason err != ERR_OK */
else if (err != ERR_OK)
{
	/* free received pbuf*/
	if (p != NULL)
	{
		pbuf_free(p);
	}
	ret_err = err;
}
else if (es->state == ES_CONNECTED)
{
	/* increment message count */
	message_count++;

	/* Acknowledge data reception */
	tcp_recved(tpcb, p->tot_len);

	es->p_tx = p;
	char strmr[20] = "";
	strncpy(strmr, es->p_tx->payload, es->p_tx->len); // здесь считали сообщение
	printf("%d  %s\n", message_count, strmr);  

	pbuf_free(p);
	tcp_echoclient_connection_close(tpcb, es); // соединение закрывается
	ret_err = ERR_OK;
}

/* data received when connection already closed */
else
{
	/* Acknowledge data reception */
	tcp_recved(tpcb, p->tot_len);
	/* free pbuf and do nothing */
	pbuf_free(p);
	ret_err = ERR_OK;
}
return ret_err;
}

 

если соединение закрывать после второго сообщения,

else if(es->state == ES_CONNECTED)
 {
   /* increment message count */
   message_count++;

   /* Acknowledge data reception */
   tcp_recved(tpcb, p->tot_len);  

	es->p_tx = p;
	char strmr[20] = "";
	strncpy (strmr,es->p_tx->payload,es->p_tx->len);
	//strmr[es->p_tx->len] = '\r';
   printf ("%d  %s\n", message_count, strmr);

	if (strncmp(strmr, "OK", 2) == 0)
	{
				pbuf_free(p);
	}
	else
	{
			pbuf_free(p);
			tcp_echoclient_connection_close(tpcb, es);
	}	
   ret_err = ERR_OK;
 }

то происходит переполнение буфера и ...

1 OK

2 4680235013820

3 OK

4 4680235013820

5 OK

6 4680235013820

7 OK

8 4680235013820

9 OK

10 4680235013820

11 OK

Assertion "pbuf_free: p->ref > 0" failed at line 747 in ../Middlewares/Third_Party/LwIP/src/core/pbuf.c

Assertion "mem_free: legal memory" failed at line 430 in ../Middlewares/Third_Party/LwIP/src/core/mem.c

Assertion "pbuf_free: p->ref > 0" failed at line 747 in ../Middlewares/Third_Party/LwIP/src/core/pbuf.c

Assertion "tcp_write: arg == NULL (programmer violates API)" failed at line 401 in ../Middlewares/Third_Party/LwIP/src/core/tcp_out.c

Assertion "tcp_write: arg == NULL (programmer violates API)" failed at line 401 in ../Middlewares/Third_Party/LwIP/src/core/tcp_out.c

12 ER

:smile3046:

 

 

попробовал с компьютера в visual studio написать запрос

 

187 - запрос "M\r"

192 - ответ "OK\r"

198 - ответ "4680235013820"

 

2018-05-31_11-15-40.png

 

подскажите пожалуйста как правильно организовать прием второго пакета

Изменено пользователем realqwerty

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вроде-бы lwIp работает точно так-же как терминал - учитывает управляющий символ строки. Если конечно это не вырезано с корнем.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Вроде-бы lwIp работает точно так-же как терминал - учитывает управляющий символ строки. Если конечно это не вырезано с корнем.

Это из рубрики "вредные советы". Lwip вообще не заглядывает в данные, когда речь идёт о голом TCP.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нужно просто переписать эхоклиент из примера под свою задачу. Для этого нужно просто разобраться с основными функциями lwip и принципом его работы. Возьмите для начала в качестве сервера терминалку hercules

Изменено пользователем 0men

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Нужно просто переписать эхоклиент из примера под свою задачу. Для этого нужно просто разобраться с основными функциями lwip и принципом его работы. Возьмите для начала в качестве сервера терминалку hercules

В своё время смотрел на это эхо в качестве примера. Слишком там замудрёно, особенно для новичка. Я бы советовал посмотреть на веб сервер, там есть пара полезных идей. Правда, код перегружен вот этой условной компиляцией, но куда деваться?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

а на халяву не прокатит: "тут" поставить очистку буфера, а "тут" отключение соединения?

Изменено пользователем realqwerty

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
В своё время смотрел на это эхо в качестве примера. Слишком там замудрёно, особенно для новичка. Я бы советовал посмотреть на веб сервер, там есть пара полезных идей. Правда, код перегружен вот этой условной компиляцией, но куда деваться?

 

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

Изменено пользователем 0men

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
имеется сервер...как правильно организовать прием второго пакета

 

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

в процессе рихтования - большая вероятность, что сами и обнаружите ляпы...

 

удачи вам

(круглый)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Это из рубрики "вредные советы".

Ну значит вырезано.

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

сделал с использованием сокетов, получилось неожиданно легко, где будут грабли?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти
Авторизация