скрытое меню

GET запросы к HTTP серверу

Обновляем проект http сервера на STM32 . Среда Atollic True Studio.

Используем TCP стек LWIP 1.4.1 без динамического выделения памяти типа malloc , только память типа PBUF_POOL .

По-поводу FreeRTOS используем вариант только static . То есть никакого динамического выделения памяти, только из заранее зарезервированной на этапе компиляции программы.

Вместо Ethernet канала у нас происходит эмуляция сетевой карты через USB канал ( реализован RNDIS адаптер). Но это в общем-то особой роли для работы TCP стека не имеет.

Получение контента от сервера

GET запросы обычно характерны тем , что объем данных от клиента меньше (сам запрос), а ответ сервера обычно намного больше (по количеству пакетов пакетов[сегментов])..

Рассмотрим происходит запрос главной страницы GET http://192.168.7.1/ . И посмотрим какие регионы памяти задействуются при этом.

Сначала первым всегда приходит SYN сегмент от клиента. Все входящие сегменты помещаются в регион [PBUF_POOL] .


15936 :                [PBUF_POOL] memp 20003F18 size=1540 num=8 free memp:200063C0 free block:200063D4
15936 :                	20003F2C [0] 	20004548 [0] 	20004B64 [0] 	20005180 [0] 	2000579C [0] 	20005DB8 [0] 	200063D4 [0] 
15937 :                	200069F0 [1] :
15937 :                		next:0 len=52 tot_len=52 ref=1  flags=x0 
15937 :                			 0x45 0x00 0x00 0x34 0xF4 0x40 0x40 0x00 0x80 0x06 0x77 0x2E 0xC0 0xA8 0x07 0x03 0xC0 0xA8 0x07 0x01 0xEB 0x7C 0x00 0x50 0x8C 0x81 0xD0 0x26 0x00 0x00 0x00 0x00 0x80 0x02 0xFA 0xF0 0x9C 0x55 0x00 0x00 0x02 0x04 0x05 0xB4 0x01 0x03 0x03 0x08 0x01 0x01 0x04 0x02

Наш сервер открывает TCP соединение и создает блок памяти в регионе [TCP_PCB] :


15941 : ------------ > tcp_input
15941 :                TCP header:
15941 :                +-------------------------------+
15941 :                |    60284      |       80      | (src port, dest port)
15941 :                +-------------------------------+
15942 :                |           2357317670          | (seq no) [2357317670]
15942 :                +-------------------------------+
15942 :                |           0000000000          | (ack no) [0]
15942 :                +-------------------------------+
15943 :                |  8 |   |000010|     64240     | (hdrlen, flags (SYN ), win)
15943 :                +-------------------------------+
15943 :                |    0x9c55     |         0     | (chksum, urgp)
15944 :                +-------------------------------+
15944 : ---------------- > pbuf_header
15944 :                    pbuf_header: old 20006A0E new 20006A22 (-20)
15944 : ---------------- < pbuf_header
15944 : ---------------- > pbuf_header
15944 :                    pbuf_header: old 20006A22 new 20006A42 (-32)
15945 : ---------------- < pbuf_header
15945 :                tcp_input: packed for LISTENing connection.
15945 : ---------------- > tcp_listen_input
15945 :                    TCP connection request 60284 -> 80.
15946 : -------------------- > tcp_alloc
15946 : ------------------------ > memp_malloc_fn
15946 : ---------------------------- > memp_overflow_check_all
15946 : ---------------------------- < memp_overflow_check_all
15947 :                            memp:200035D0 memp_sizes[TCP_PCB] size=160 
15947 : ------------------------ < memp_malloc_fn

15947 :                        [TCP_PCB] memp 20003518 size=160 num=2 free memp:20003518 free block:2000352C
15948 :                        	2000352C [0] 
15948 :                        	200035E4 [1] :
15948 :                        		ttl 536884708	 tos 255	 polltmr 0	 pollinterval 0	 last_timer 0	 tmr 96
15948 :                        		rcv_nxt [0]	 rcv_wnd 2920	 rcv_ann_wnd 2920	 rcv_ann_right_edge [0]
15949 :                        		rtime -1	 mss 536	 rttest 0	 rtseq 0	 sa 0	 sv 6	 rto 6	 nrtx 0
15949 :                        		dupacks 0  lastack 6542  cwnd 1  ssthresh 0  snd_nxt 6542  snd_wl1 0  snd_wl2 6542

Тут же создается таймер для слежения за соединением. Чтобы не было висяков и через пару минут простоя закрывать соединение.


15950 : -------------------- > tcp_timer_needed
15950 : ------------------------ > sys_timeout
15951 : ---------------------------- > memp_malloc_fn
15951 : -------------------------------- > memp_overflow_check_all
15951 : -------------------------------- < memp_overflow_check_all
15952 :                                memp:200038A0 memp_sizes[SYS_TIMEOUT] size=16 
15952 : ---------------------------- < memp_malloc_fn
15952 :                            200038b4 timeout->next=0 timeout->time=250
15952 :                            200038b4 timeout->next=200038DC timeout->time=250
15953 : ------------------------ < sys_timeout
15953 : -------------------- < tcp_timer_needed

Далее сервер переходит к созданию ответа (пакет SYN/ACK)

Тут задейтсвуются регионы памяти [TCP_SEG] и [MALLOC_256] . Создаем сегмент для посылки клиенту.

Сначала содержание пакета помещается в регион [MALLOC_256] . Это потому , что указан параметр PBUF_RAM (тип памяти).


15955 : ------------------------ > pbuf_alloc
15955 :                            layer=[PBUF_TRANSPORT] offset=54 type=[PBUF_RAM] 
15956 : ---------------------------- > mem_malloc
15956 :                                size=76 required_size=80
15956 : -------------------------------- > memp_malloc_fn
15956 : ------------------------------------ > memp_overflow_check_all
15957 : ------------------------------------ < memp_overflow_check_all
15957 :                                    memp:2000734C memp_sizes[MALLOC_256] size=260 
15957 : -------------------------------- < memp_malloc_fn
15957 :                                pbuf:20007364
15958 : ---------------------------- < mem_malloc
15958 : ------------------------ < pbuf_alloc

Потом создается блок памяти в регионе [TCP_SEG] . Тут делается запись , что есть сегмент и он будет отправлен. Но запись о нем мы будем хранить здесь пока не придет от клиента подтверждение (ACK пакет), что он получен.


15958 : ------------------------ > tcp_create_segment
15958 : ---------------------------- > memp_malloc_fn
15959 : -------------------------------- > memp_overflow_check_all
15959 : -------------------------------- < memp_overflow_check_all
15959 :                                memp:20003824 memp_sizes[TCP_SEG] size=20 
15959 : ---------------------------- < memp_malloc_fn
15960 : ---------------------------- > pbuf_header
15960 :                                pbuf_header: old 200073AC new 20007398 (20)
15960 : ---------------------------- < pbuf_header

15960 :                            [TCP_SEG] memp 200036F0 size=20 num=8 free memp:200037F8 free block:2000380C
15961 :                            	20003704 [0] 	20003730 [0] 	2000375C [0] 	20003788 [0] 	200037B4 [0] 	200037E0 [0] 	2000380C [0] 
15962 :                            	20003838 [1] :
15962 :                            				20003838 len=0 next:0 pbuf:20007364 flags=1 

15966 :                            [MALLOC_256] memp 20006FF8 size=260 num=4 free memp:20007230 free block:20007244
15966 :                            	2000700C [0] 	20007128 [0] 	20007244 [0] 
15966 :                            	20007360 [1] :
15967 :                            		20007364 payload 20007398 next:0 len=24 ref=1 tot_len=24 flags=x0 
15967 :                            			 0x00 0x50 0xEB 0x7C 0x00 0x00 0x19 0x8E 0x00 0x00 0x00 0x00 0x60 0x12 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
15969 : ------------------------ < tcp_create_segment

Далее мы (сервер) ждем от клиента подтверждение на SYN пакет . И клиент присылает ACK и возможно уже с данными (PSH).

Как обычно пришедший сегмент сначала размещается в [PBUF_POOL].

Тут сервер понимает , что соединение подтверждено и создает запись в регионе [HTTPD_STATE], чем фиксирует открытие соединения HTTP.

16299 : -------------------- > http_accept
16299 :                        http_accept tcp_pcb*: 200035E4 / 200036D0
16299 : ------------------------ > http_state_alloc
16299 : ---------------------------- > memp_malloc_fn
16300 : -------------------------------- > memp_overflow_check_all
16300 : -------------------------------- < memp_overflow_check_all
16300 :                                memp:20003B40 memp_sizes[HTTPD_STATE] size=192 
16301 : ---------------------------- < memp_malloc_fn
16301 : ---------------------------- > http_state_init
16301 : ---------------------------- < http_state_init
16301 : ------------------------ < http_state_alloc
16302 : -------------------- < http_accept

Потом мы видим , что это имеено подтверждение нашего пакета SYN и тогда очищаем запись в [TCP_SEG] с содержанием в [MALLOC_256]:


6302 : -------------------- > tcp_receive
16302 :                        		while ( pcb->unacked...
16302 : ------------------------ > tcp_seg_free
16302 :                            tcp_seg_free: 20003838  seg : pbuf:20007364  len=0 oversize_left=0
16303 : ---------------------------- > pbuf_free
16303 :                                pbuf_free: pbuf:20007364 [PBUF_RAM]
16303 :                                pbuf_free: deallocating 20007364 [PBUF_RAM]
16304 : -------------------------------- > memp_overflow_check_all
16304 : -------------------------------- < memp_overflow_check_all
16304 :                                memp_free memp:2000734C [MALLOC_256]
16305 : ---------------------------- < pbuf_free
16305 : ---------------------------- > memp_overflow_check_all
16305 : ---------------------------- < memp_overflow_check_all
16305 :                            memp_free memp:20003824 [TCP_SEG]
16306 : ------------------------ < tcp_seg_free
16306 :                        		!-- seqno is fit to current window --!
16306 : ------------------------ > tcp_update_rcv_ann_wnd
16306 : ------------------------ < tcp_update_rcv_ann_wnd
16307 :                        ooseq : 

16307 : -------------------- < tcp_receive

На этом этапе мы еще только установили соединение и получили данные (запрос страницы) от клиента.

У нас на данный момент используются следующие регионы памяти:


16308 :                        [UDP_PCB] memp 200034E0 size=32 num=1 free memp:0 free block:14
16308 :                        	200034F4 [1] :
16309 :                        		next:0 local_port:67 

16309 :                        [TCP_PCB] memp 20003518 size=160 num=2 free memp:20003518 free block:2000352C
16309 :                        	2000352C [0] 
16309 :                        	200035E4 [1] :
16310 :                        		ttl 536884708	 tos 255	 polltmr 0	 pollinterval 0	 last_timer 4	 tmr 98
16310 :                        		rcv_nxt [218]	 rcv_wnd 2702	 rcv_ann_wnd 2702	 rcv_ann_right_edge [2920]
16310 :                        		rtime -1	 mss 1460	 rttest 0	 rtseq 6542	 sa 1	 sv 6	 rto 6	 nrtx 0
16311 :                        		dupacks 0  lastack 6543  cwnd 2920  ssthresh 64240  snd_nxt 6543  snd_wl1 2357317671  snd_wl2 6543
 
16311 :                        [TCP_PCB_LISTEN] memp 20003688 size=28 num=2 free memp:20003688 free block:2000369C
16312 :                        	2000369C [0] 
16312 :                        	200036D0 [1] :
16312 :                        		200036D0: ttl=255 port=80 tos=0

16314 :                        [SYS_TIMEOUT] memp 20003850 size=16 num=4 free memp:20003878 free block:2000388C
16314 :                        	20003864 [0] 	2000388C [0] 
16314 :                        	200038B4 [1] :
16315 :                        		next:200038DC time:250
16315 :                        	200038DC [1] :
16315 :                        		next:0 time:4750

16316 :                        [HTTPD_STATE] memp 20003B40 size=192 num=1 free memp:0 free block:14
16316 :                        	20003B54 [1] :
16317 :                        				20003B54: tcp_pcb:200035E4 post_content_len_left=0 

16319 :                        [PBUF_POOL] memp 20003F18 size=1540 num=8 free memp:200063C0 free block:200063D4
16319 :                        	20003F2C [0] 	20004548 [0] 	20004B64 [0] 	20005180 [0] 	2000579C [0] 	20005DB8 [0] 	200063D4 [0] 
16320 :                        	200069F0 [1] :
16320 :                        		next:0 len=218 tot_len=218 ref=1  flags=x1 
16320 :                        			 0x47 0x45 0x54 0x20 0x2F 0x20 0x48 0x54 0x54 0x50 0x2F 0x31 0x2E 0x31 0x0D 0x0A 0x63 0x61 0x63 0x68 0x65 0x2D 0x63 0x6F 0x6E 0x74 0x72 0x6F 0x6C 0x3A 0x20 0x6E 0x6F 0x2D 0x63 0x61 0x63 0x68 0x65 0x0D 0x0A 0x50 0x6F 0x73 0x74 0x6D 0x61 0x6E 0x2D 0x54 0x6F 0x6B 0x65 0x6E 0x3A 0x20 0x31 0x64 0x37 0x37 0x38 0x62 0x35 0x36 0x2D 0x64 0x61 0x32 0x66 0x2D 0x34 0x30 0x39 0x34 0x2D 0x38 0x38 0x62 0x38 0x2D 0x66 0x33 0x66 0x36 0x38 0x30 0x38 0x36 0x63 0x66 0x38 0x63 0x0D 0x0A 0x55 0x73 0x65 0x72 0x2D 0x41 0x67 0x65 0x6E 0x74 0x3A 0x20 0x50 0x6F 0x73 0x74 0x6D 0x61 0x6E 0x52 0x75 0x6E 0x74 0x69 0x6D 0x65 0x2F 0x37 0x2E 0x36 0x2E 0x30 0x0D 0x0A 0x41 0x63 0x63 0x65 0x70 0x74 0x3A 0x20 0x2A 0x2F 0x2A 0x0D 0x0A 0x48 0x6F 0x73 0x74 0x3A 0x20 0x31 0x39 0x32 0x2E 0x31 0x36 0x38 0x2E 0x37 0x2E 0x31 0x0D 0x0A 0x61 0x63 0x63 0x65 0x70 0x74 0x2D 0x65 0x6E 0x63 0x6F 0x64 0x69 0x6E 0x67 0x3A 0x20 0x67 0x7A 0x69 0x70 0x2C 0x20 0x64 0x65 0x66 0x6C 0x61 0x74 0x65 0x0D 0x0A 0x43 0x6F 0x6E 0x6E 0x65 0x63 0x74 0x69 0x6F 0x6E 0x3A 0x20 0x6B 0x65 0x65 0x70 0x2D 0x61 0x6C 0x69 0x76 0x65 0x0D 0x0A 0x0D 0x0A

Теперь сервер переходит к подготовке ответа клиенту , то есть отдачи запрашиваемой страницы.

Сначала сервер анализирует содержание запроса, понимает что он будет отдавать и очищает содержание принятого пакета от клиента в [PBUF_POOL].

Далее сервер (в нашем частно случае) готовит 2 сегмента на оправку, так как содержание более 2 сегментов , а размер окна для отправки равно 2 сегментам (по 1460).

Содержание страницы размещено во FLASH (заранее скомпилированное) и поэтому тип памяти с содежанием [PBUF_ROM], то есть из FLASH памяти контроллера. Мы создаем запись в регионе памяти [PBUF_REF/ROM] со ссылкой на содержание.

И еще создаем запись в регионе [MALLOC_256] и в [TCP_SEG] . Все это связываем между собой.

И это повторяем дважды , так сегмента на отправку у нас 2 штуки.


16414 :                                Trying go send 2920 bytes
16414 : -------------------------------- > tcp_write
16415 :                                    tcp_write(pcb=0x200035e4, data=0x8024594, len=2920, apiflags=0)
16415 : ------------------------------------ > tcp_write_checks
16415 :                                        tcp_write: queuelen: 0
16415 : ------------------------------------ < tcp_write_checks
16416 : ------------------------------------ > pbuf_alloc
16416 :                                        layer=[PBUF_TRANSPORT] offset=54 type=[PBUF_ROM] 
16416 : ---------------------------------------- > memp_malloc_fn
16417 : -------------------------------------------- > memp_overflow_check_all
16417 : -------------------------------------------- < memp_overflow_check_all
16417 :                                            memp:20003EE8 memp_sizes[PBUF_REF/ROM] size=24 
16418 : ---------------------------------------- < memp_malloc_fn
16418 : ------------------------------------ < pbuf_alloc
16418 : ------------------------------------ > pbuf_alloc
16419 :                                        layer=[PBUF_TRANSPORT] offset=54 type=[PBUF_RAM] 
16419 : ---------------------------------------- > mem_malloc
16419 :                                            size=72 required_size=76
16419 : -------------------------------------------- > memp_malloc_fn
16420 : ------------------------------------------------ > memp_overflow_check_all
16420 : ------------------------------------------------ < memp_overflow_check_all
16421 :                                                memp:2000734C memp_sizes[MALLOC_256] size=260 
16421 : -------------------------------------------- < memp_malloc_fn
16421 :                                            pbuf:20007364
16422 : ---------------------------------------- < mem_malloc
16422 : ------------------------------------ < pbuf_alloc
16422 : ------------------------------------ > pbuf_cat
16422 : ------------------------------------ < pbuf_cat
16422 : ------------------------------------ > tcp_create_segment
16423 : ---------------------------------------- > memp_malloc_fn
16423 : -------------------------------------------- > memp_overflow_check_all
16423 : -------------------------------------------- < memp_overflow_check_all
16424 :                                            memp:20003824 memp_sizes[TCP_SEG] size=20 
16424 : ---------------------------------------- < memp_malloc_fn
16424 : ---------------------------------------- > pbuf_header
16425 :                                            pbuf_header: old 200073AC new 20007398 (20)
16425 : ---------------------------------------- < pbuf_header

16435 : ------------------------------------ < tcp_create_segment
16435 :                                    tcp_write: queueing 6543:8003
16435 : ------------------------------------ > pbuf_alloc
16436 :                                        layer=[PBUF_TRANSPORT] offset=54 type=[PBUF_ROM] 
16436 : ---------------------------------------- > memp_malloc_fn
16436 : -------------------------------------------- > memp_overflow_check_all
16437 : -------------------------------------------- < memp_overflow_check_all
16437 :                                            memp:20003EB8 memp_sizes[PBUF_REF/ROM] size=24 
16438 : ---------------------------------------- < memp_malloc_fn
16438 : ------------------------------------ < pbuf_alloc
16438 : ------------------------------------ > pbuf_alloc
16438 :                                        layer=[PBUF_TRANSPORT] offset=54 type=[PBUF_RAM] 
16439 : ---------------------------------------- > mem_malloc
16439 :                                            size=72 required_size=76
16439 : -------------------------------------------- > memp_malloc_fn
16440 : ------------------------------------------------ > memp_overflow_check_all
16440 : ------------------------------------------------ < memp_overflow_check_all
16440 :                                                memp:20007230 memp_sizes[MALLOC_256] size=260 
16441 : -------------------------------------------- < memp_malloc_fn
16441 :                                            pbuf:20007248
16441 : ---------------------------------------- < mem_malloc
16442 : ------------------------------------ < pbuf_alloc
16442 : ------------------------------------ > pbuf_cat
16442 : ------------------------------------ < pbuf_cat
16442 : ------------------------------------ > tcp_create_segment
16442 : ---------------------------------------- > memp_malloc_fn
16443 : -------------------------------------------- > memp_overflow_check_all
16443 : -------------------------------------------- < memp_overflow_check_all
16443 :                                            memp:200037F8 memp_sizes[TCP_SEG] size=20 
16444 : ---------------------------------------- < memp_malloc_fn
16444 : ---------------------------------------- > pbuf_header
16444 :                                            pbuf_header: old 20007290 new 2000727C (20)
16445 : ---------------------------------------- < pbuf_header

16445 :                                        [TCP_SEG] memp 200036F0 size=20 num=8 free memp:200037CC free block:200037E0
16446 :                                        	20003704 [0] 	20003730 [0] 	2000375C [0] 	20003788 [0] 	200037B4 [0] 	200037E0 [0] 
16446 :                                        	2000380C [1] :
16446 :                                        				2000380C len=1460 next:0 pbuf:20007248 flags=0 
16447 :                                        	20003838 [1] :
16447 :                                        				20003838 len=1460 next:0 pbuf:20007364 flags=0 

16448 :                                        [PBUF_REF/ROM] memp 20003C18 size=24 num=16 free memp:20003E88 free block:20003E9C
16448 :                                        	20003C2C [0] 	20003C5C [0] 	20003C8C [0] 	20003CBC [0] 	20003CEC [0] 	20003D1C [0] 	20003D4C [0] 	20003D7C [0] 	20003DAC [0] 	20003DDC [0] 	20003E0C [0] 	20003E3C [0] 	20003E6C [0] 	20003E9C [0] 
16449 :                                        	20003ECC [1] :
16449 :                                        			 0x00 0x00 0x00 0x00 0x48 0x4B 0x02 0x08 0xB4 0x05
16450 :                                        	20003EFC [1] :
16450 :                                        			 0x00 0x00 0x00 0x00 0x94 0x45 0x02 0x08 0xB4 0x05

16451 :                                        [PBUF_POOL] memp 20003F18 size=1540 num=8 free memp:200069DC free block:200069F0
16451 :                                        	20003F2C [0] 	20004548 [0] 	20004B64 [0] 	20005180 [0] 	2000579C [0] 	20005DB8 [0] 	200063D4 [0] 	200069F0 [0] 

16452 :                                        [MALLOC_256] memp 20006FF8 size=260 num=4 free memp:20007114 free block:20007128
16452 :                                        	2000700C [0] 	20007128 [0] 
16453 :                                        	20007244 [1] :
16453 :                                        		20007248 payload 2000727C next:20003ECC len=20 ref=1 tot_len=1480 flags=x0 
16454 :                                        			 0x00 0x50 0xEB 0x7C 0x00 0x00 0x1F 0x43 0x00 0x00 0x00 0x00 0x50 0x00 0x00 0x00 0x00 0x00 0x00 0x00
16454 :                                        	20007360 [1] :
16455 :                                        		20007364 payload 20007398 next:20003EFC len=20 ref=1 tot_len=1480 flags=x0 
16455 :                                        			 0x00 0x50 0xEB 0x7C 0x00 0x00 0x19 0x8F 0x00 0x00 0x00 0x00 0x50 0x00 0x00 0x00 0x00 0x00 0x00 0x00

16456 :                                        [MALLOC_512] memp 20007468 size=516 num=1 free memp:20007468 free block:2000747C
16456 :                                        	2000747C [0] 

16457 :                                        [MALLOC_1512] memp 20007684 size=1516 num=1 free memp:20007684 free block:20007698
16457 :                                        	20007698 [0] 
16457 : ------------------------------------ < tcp_create_segment
16458 :                                    tcp_write: queueing 8003:9463
16458 :                                    tcp_write: 4 (after enqueued)
16458 : -------------------------------- < tcp_write
16459 :                                Sent 2920 bytes
16459 : ---------------------------- < http_write

Свзяь [MALLOC_256] , [TCP_SEG] и [PBUF_REF/ROM] такая : голова это [TCP_SEG]. [TCP_SEG] в параметре pbuf указывает на [MALLOC_256] . [MALLOC_256] в свою очередь в параметре next указывает на запись [PBUF_REF/ROM] , которая в свю очередь указывает на адрес FLASH памяти , где хранится содержание отдаваемой страницы.

Далее происходит отсылка наших двух сегментов и сервер ожидает от клиента подтверждения, который конечно же помещается в [PBUF_POOL].

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


16600 : ---------------- > tcp_process
16601 :                    tcp_process:
16601 :                    tcp_process: case ESTABLISHED
16601 : -------------------- > tcp_receive
16601 :                        		while ( pcb->unacked...
16601 : ------------------------ > tcp_seg_free
16602 :                            tcp_seg_free: 20003838  seg : pbuf:20007364  len=1460 oversize_left=0
16602 : ---------------------------- > pbuf_free
16602 :                                pbuf_free: pbuf:20007364 [PBUF_RAM]
16603 :                                pbuf_free: deallocating 20007364 [PBUF_RAM]
16603 : -------------------------------- > memp_overflow_check_all
16603 : -------------------------------- < memp_overflow_check_all
16603 :                                memp_free memp:2000734C [MALLOC_256]
16604 :                                pbuf_free: deallocating 20003EFC [PBUF_ROM]
16604 : -------------------------------- > memp_overflow_check_all
16604 : -------------------------------- < memp_overflow_check_all
16605 :                                memp_free memp:20003EE8 [PBUF_REF/ROM]
16605 : ---------------------------- < pbuf_free
16605 : ---------------------------- > memp_overflow_check_all
16606 : ---------------------------- < memp_overflow_check_all
16606 :                            memp_free memp:20003824 [TCP_SEG]
16606 : ------------------------ < tcp_seg_free
16606 :                        ooseq : 

16606 : -------------------- < tcp_receive
16607 : ---------------- < tcp_process

Второй пакет клиент не подтвердил , но мы можем уже передать еще один (у нас он поледний , это остаток), что сервер и делает, так как размер окна позволяет (окно сдвинулось на 1 сегмент и появилось место для следующего пакета).

В результате клиент (в конкретном частном случае) присылает уже с ACK и FIN . Сервер по параметрам Seq и Ack пакета клиента видит ,что все его сервера пакеты подверждены и очищает связи [TCP_SEG] ->[MALLOC_256] -> [PBUF_REF/ROM] (оставшиеся 2 цепочки).


16725 :                +-+-+-+-+-+-+-+-+-+-+-+-+-+- 
16725 :                tcp_input: flags FIN ACK 
16726 :                -+-+-+-+-+-+-+-+-+-+-+-+-+-+
16726 :                TCP State: FIN_WAIT_1
16726 : ---------------- > tcp_process
16726 :                    tcp_process:
16726 :                    tcp_process: case FIN_WAIT_1
16727 : -------------------- > tcp_receive
16727 :                        		while ( pcb->unacked...
16727 : ------------------------ > tcp_seg_free
16727 :                            tcp_seg_free: 2000380C  seg : pbuf:20007248  len=1460 oversize_left=0
16728 : ---------------------------- > pbuf_free
16728 :                                pbuf_free: pbuf:20007248 [PBUF_RAM]
16728 :                                pbuf_free: deallocating 20007248 [PBUF_RAM]
16728 : -------------------------------- > memp_overflow_check_all
16729 : -------------------------------- < memp_overflow_check_all
16729 :                                memp_free memp:20007230 [MALLOC_256]
16729 :                                pbuf_free: deallocating 20003ECC [PBUF_ROM]
16730 : -------------------------------- > memp_overflow_check_all
16730 : -------------------------------- < memp_overflow_check_all
16730 :                                memp_free memp:20003EB8 [PBUF_REF/ROM]
16731 : ---------------------------- < pbuf_free
16731 : ---------------------------- > memp_overflow_check_all
16731 : ---------------------------- < memp_overflow_check_all
16731 :                            memp_free memp:200037F8 [TCP_SEG]
16732 : ------------------------ < tcp_seg_free
16732 : ------------------------ > tcp_seg_free
16732 :                            tcp_seg_free: 20003838  seg : pbuf:20007364  len=717 oversize_left=0
16732 : ---------------------------- > pbuf_free
16733 :                                pbuf_free: pbuf:20007364 [PBUF_RAM]
16733 :                                pbuf_free: deallocating 20007364 [PBUF_RAM]
16733 : -------------------------------- > memp_overflow_check_all
16734 : -------------------------------- < memp_overflow_check_all
16734 :                                memp_free memp:2000734C [MALLOC_256]
16734 :                                pbuf_free: deallocating 20003EFC [PBUF_ROM]
16735 : -------------------------------- > memp_overflow_check_all
16735 : -------------------------------- < memp_overflow_check_all
16735 :                                memp_free memp:20003EE8 [PBUF_REF/ROM]
16735 : ---------------------------- < pbuf_free
16736 : ---------------------------- > memp_overflow_check_all
16736 : ---------------------------- < memp_overflow_check_all
16736 :                            memp_free memp:20003824 [TCP_SEG]
16737 : ------------------------ < tcp_seg_free
16737 :                        		!-- seqno is fit to current window --!
16737 : ------------------------ > tcp_update_rcv_ann_wnd
16737 : ------------------------ < tcp_update_rcv_ann_wnd
16737 :                        ooseq : 

16738 : -------------------- < tcp_receive
16738 :                    TCP connection closed: FIN_WAIT_1 60284 -> 80.
16738 : -------------------- > tcp_pcb_purge
16738 :                        tcp_pcb_purge
16738 : ------------------------ > tcp_segs_free
16739 : ------------------------ < tcp_segs_free
16739 : ------------------------ > tcp_segs_free
16739 : ------------------------ < tcp_segs_free
16739 : ------------------------ > tcp_segs_free
16739 : ------------------------ < tcp_segs_free
16740 : -------------------- < tcp_pcb_purge
TCP_RMV: removing 0x200035e4 from 0x200035e4
TCP_RMV: removed 0x200035e4 from 0
TCP_REG 0x200035e4 local port 80
16740 : -------------------- > tcp_timer_needed
16740 : -------------------- < tcp_timer_needed
16741 : ---------------- < tcp_process

Сервер получил с пакетом флаг FIN и понял, что клиент все получил и хочет закрыть соединение. Серверу оастается только послать ACK клиекнту и сервер считает , что соединение закрылось.

Для последнего пакета достаточно использоваьб только память региона [MALLOC_256], так как это пакет нулевой длины (без контента):

16742 : ---------------------------- > pbuf_alloc
16742 :                                layer=[PBUF_IP] offset=34 type=[PBUF_RAM] 
16742 : -------------------------------- > mem_malloc
16742 :                                    size=72 required_size=76
16743 : ------------------------------------ > memp_malloc_fn
16743 : ---------------------------------------- > memp_overflow_check_all
16743 : ---------------------------------------- < memp_overflow_check_all
16744 :                                        memp:2000734C memp_sizes[MALLOC_256] size=260 
16744 : ------------------------------------ < memp_malloc_fn
16744 :                                    pbuf:20007364
16744 : -------------------------------- < mem_malloc
16745 : ---------------------------- < pbuf_alloc

Установка значения в контроллере

Вот так примерно выглядит наш запрос галвной страницы с нашего http сервера.
Также мы можем менять настройки контроллера STM32 через http GET запросы :

фотка 1

Для нашей http страницы браузер несколько раз открывает TCP соединение , передает GET запрос, закрывает соединение. Несколько раз потому ,что для каждого ресурса страницы нашего сайта. То есть саму страницу, файл zepto.min.js, favicon.ico и еще Касперский умудряется вклинится и сделать свои (как он считает) важные запросы.

По идеалогии LWIP мы сами подключаем необходимые файлы к нашему http серверу. Например как аналог JQuery у нас используется файл zepto.min.js (Zepto v1.1.6) . Все эти файлы надо сначала закомпилировать в выходной файл fsdata.c.

Вот примерный tcp траффик из программы WinShark из которого можно разобрать ,что браузер несколько раз последовательно открыл соединение , произвел обмен данными и закрыл соединение.

фотка 2

Красной рамкой обведен первый запрос - это контент страницы. Синей рамкой обведен следующий запрос - это содержания файла zepto.min.js .

Когда браузер уже загрузил страницу идет запрос GET /state.cgi . Он генерируется из js ( js функционал реализован в файле zepto.min.js) по событию OnReady.

На запрос GET /state.cgi контроллер отвечает json пакетом данных , которые мы на стороне клиента (в браузере) получаем , обрабатываем и заполняем поля ввода нашей страницы .

Из всех запросов запрос файла zepto.min.js получается самым тяжеловесным (примерно 26Кб).