Jump to content

    

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

 

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

Edited by realqwerty

Share this post


Link to post
Share on other sites

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

 

Share this post


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

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

Share this post


Link to post
Share on other sites

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

Edited by 0men

Share this post


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

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

Share this post


Link to post
Share on other sites

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

Edited by realqwerty

Share this post


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

 

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

Edited by 0men

Share this post


Link to post
Share on other sites
имеется сервер...как правильно организовать прием второго пакета

 

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

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

 

удачи вам

(круглый)

 

Share this post


Link to post
Share on other sites
Это из рубрики "вредные советы".

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

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

 

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this