概述
什么是半双工?什么是全双工模式?
lwip_commom_init()函数分析:
netif_add()函数中参数lwip_netip中定义了网络接口,这个函数除了IP地址、子网掩码、默认网关,还包括了两个函数地址作为参数,ethernetif_init和ethernet_input。这两个函数地址会赋值到netif结构体的相关字段。ethernetif_init()在下一节中将会讲到,这个函数函数由ALIENTEK提供,ethernet_input()函数在etharp.c文件中,属于LWIP源码,是ARP层数据包输入函数。
Netif_Init_Flag=netif_add(&lwip_netif,&ipaddr,&netmask,&gw,NULL,ðernetif_init,ðernet_input);该函数最后两个参数是一个函数指针,该函数是有输入参数的函数。其函数定义为:
typedef err_t (*netif_init_fn)(struct netif *netif);
typedef err_t (*netif_input_fn)(struct pbuf *p, struct netif *inp);
由上可知,实际上是
同时将IP、子网掩码、网关和两个函数添加在网卡列表中。
7、如果使用
DHCP的话就开启DHCP服务,通过调用dhcp_start()函数开启DHCP服务。使用DHCP服 务来获取IP地址、子网掩码和默认网关等信息,如果使用静态IP地址的话就 ip_comm_default_ip_set()函数设置的地址信息。
8、使用dhcp获取iplwIP中主要有memp.h, memp_std.h, memp.c, mem.h, mem.c几个类组成了内存管理模块。
9. 一、tcppcbnew = tcp_new();//创建一个新的pcb,该TCP protocol控制块不放入任何
PCB列表中,直到绑定(即二步骤),才放入列表中!!!!
->tcp_alloc(TCP_PRIO_NORMAL); //TCP_PRIO_NORMAL = 64;
->pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB);
->(MEMP_TCP_PCB难点)
if LWIP_TCP
LWIP_MEMPOOL(TCP_PCB, MEMP_NUM_TCP_PCB, sizeof(struct tcp_pcb), "TCP_PCB")
LWIP_MEMPOOL(TCP_PCB_LISTEN, MEMP_NUM_TCP_PCB_LISTEN, sizeof(struct tcp_pcb_listen), "TCP_PCB_LISTEN")
LWIP_MEMPOOL(TCP_SEG, MEMP_NUM_TCP_SEG, sizeof(struct tcp_seg), "TCP_SEG")
#endif /* LWIP_TCP */
->(LWIP_MEMPOOL难点)
typedef enum{
#define LWIP_MEMPOOL(name, num,size,desc) MEMP_##name,
#include "lwip/memp_std.h"
MEMP_MAX
}memp_t;
1、该枚举类型将
2、如果定义了LWIP_TCP_PCB,则
->(memp_malloc()难点) if !MEMP_OVERFLOW_CHECK //opt.h中定义了MEMP_OVERFLOW_CHECK=0
memp_malloc(memp_t type)#else
memp_malloc_fn(mem_t type,const char *file,const int line)
#endif
{
struct memp *memp;
SYS_ARCH_DECL_PROTECT(old_level);
-> #ifndef SYS_ARCH_PROECT //如果该宏定义未定义
#if SYS_LIGHTWEIGH_PORT //初始化 = 0,如果定义则宏定义下面的值
#define SYS_ARCH_DECL_PROTECT(lev) sys_prot_t lev //等同于定义了一个sys_prot_t的变量lev
#define SYS_ARCH_PROEC(lev) lev = sys_arch_protect()
#define SYS_ARCH_UNPROTECT (lev) sys_arch_unprotect(lev)
sys_prot_t sys_arch_protect(void);
void sys_arch_unprotect(sys_prot_t prval);
#else
#define SYS_ARCH_DECL_PROTECT(lev)
#define SYS_ARCH_PROTECT(lev)
#define SYS_ARCH_UNPROTECT(lev)
#endif
}
3、 上面的定义假如默认为MEMP_OVERFLOW_CHECK=0,则定义为memp_malloc(mem_t type) { }
,由上可知在c语言中的函数名也可以宏定义。
二、err = tcp_blind(tcppcbnew,IP_ADDR_ANY,TCP_SERVER_PORT); //这就是所谓的将pcb块绑定,即将端口号和本地IP绑定在一起
if(tcppcbnew == ERR_OK) //如果绑定完成 //只有这样,新建的pcb控制块才会进入监听等状态,实现功能
{
err = tcp_bind(tcppcbnew,IP_ADDR_ANY,TCP_SERVER_PORT); //设置tcppcb进入监听状态
tcp_accept(tcppcbconn,tcp_server_accept); //初始化LWIP的tcp_accpt的回调函数
//这个部分设置了newpcb的各部分的回调函数,此概念很重要!!!
// 将tcp_setver_accept函数赋给pcb控制块tcppcbconn的
}else res = 1;创建tcp_new()= tcppcbnew成功后,而且绑定完成后,res = 0,否则不会进入键盘检测。res = 0,进入键盘检测。键盘检测主要检测的是tcp_server_flag=1<<7/1<<6/1<<5来标记发送数据、收到数据、是否连接上?(涉及到重要的概念:回调函数)。
在tcp.c中都会有关于对pcb块的回调成员函数初始化的函数,tcp_recv()、tcp_err、tcp_poll()等函数,然后回调函数都是在tcp_server_demo.c中进行了定义(即应用层),利用这些接口对pcp进行操作。 其中只要绑定成功,且tcp_accpt进入监听,回调函数tcp_accept(tcppcbconn,tcp_server_accpt)成功,则1>>5在tcp_accpt()中置位。 连接上后,如果连接标志位connflag为0,则在显示连接的同时,将connflag置1,进行之后的if(connflag==1)判断。
tcp_server_flag = 1<<6;用来标记收到数据,在lwIP tcp_recv()函数的回调函数tcp_server_recv()中,接受到数据则,tcp_server_flag |= 1<<6置位。
而对于tcp_server_flag&1<<7=1条件成立,是只要按键KEY_WKUP按下即置位相应位为1,在tcp_server_poll()函数中进行调用判断即可。
总而言之,以上设置的标志位都是为了在应用层判断显示等操作,真正进行底层操作的是PCB控制块中的回调函数在起作用!!!!!!
lwip轮询任务函数:lwip_periodic_handle()中对于不同的传输方式,根据不同的条件判断:
lwip_localtime - TCPTimer->TCP_TMR_INTERVAL
lwip_localtime - ARPTimer->ARP_TMR_INIERVAL
来调用不同函数tcp_tmr()、etharp()、dhcp_fine_tmr()函数。tcp_tmr()函数中对tcp_fasttmr() 250ms调用一次 tcp_slowtmr() 500ms调用一次
tcp_fasttmr()用于每TCP_FAST_INTERVAL(250ms)处理从上层(应用层)“拒绝”回来的数据。
tcp_slowtmr()用于每500ms执行转发定时器并且该定时器将等待足够时间的的PCB移除。它同时将增量多个定时器,如PCB中的不活跃定时器。
在main()函数中我们要注意到不管是在等待DHCP完成还是DHCP成功后我们都要周期性的调用lwip_periodioc_handle()函数,因为这个函数中周期性的调用协议栈内核的一些定时函数以满足LWIP的内核要求。
最后
以上就是灵巧小虾米为你收集整理的7.9(lwip)的全部内容,希望文章能够帮你解决7.9(lwip)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复