一、网络通信实验中,app程序在编写时的异同分析:
1、tcp_server_demo.c的分析:
当利用其作为主机的时候,由于通过程序的lan8720.c的初始化,dhcp服务器的获取,ip地址已经获得。不要像client时或者udp_client时设置远程主机的ip地址来用于连接。所以只需要将本机本地ip与端口号808*相连即可。除此之外,还要进行的操作就是:tcp_listen(),作为server需要监听外部的请求状态。tcp_accept(),用于将lwip的响应回调函数初始化。(作为server时回调函数多些)
key=KEY0_PRES时,即按键KEY0_PRES按下,所做的处理仅仅将tcp_server_flag |= 1<<7;置位处理。然后将在后面的回调函数做出处理。
2、tcp_client_demo.c的分析:
tcp_client_set_remoip(): //先选择所对应的IP地址来实现
通过上面的函数来设置远程主机的ip地址,主机的ip已经在dhcp获取。然后在tcp_connect()中将tcp客户端链接到指定目的ip的指定端口号。同时链接成功后,将
tcp_client_connected()这一个函数设置为lwip回调函数。
key=KEY0_PRES时,即按键KEY0_PRES按下,所做的处理仅仅将tcp_server_flag |= 1<<7;置位处理。然后将在后面的回调函数做出处理。
3、udp_demo_test(void)的分析:
udp_demo_set_remoteip();
通过上面的函数来设置远程主机的ip地址,主机的ip已经在dhcp获取。然后在
udp_connect()中将UDP客户端链接到指定目的ip的指定端口号。
key=KEY0_PRES时, key=KEY0_PRES时,即按键KEY0_PRES按下,所做的处理是调用了udp_demo_senddata(udppcb)来处理发送。
http.c分析:
程序默认开启webserver功能,即将开发板作为电脑上浏览器http的远端服务器,利用电脑浏览器来获取stm32作为服务器上的资料和数据。
所以在作为上与tcp_server_demo.c实验的配置很相同,下面进行对比:
1、http主机服务器时:
httpd_ssi_init();
httpd_cgi_init();
pcb = tcp_new(); //创建pcb
tcp_setprio(pcb, HTTPD_TCP_PRIO); //设置pcb优先级
err = tcp_bind(pcb, local_addr, HTTPD_SERVER_PORT);//绑定本地地址与端口号
pcb = tcp_listen(pcb); //设置pcb进入监听状态
tcp_arg(pcb, pcb);
tcp_accept(pcb, http_accept);//设置tcp_accept的回调函数
2、tcp服务器时:
tcppcbnew=tcp_new(); //创建一个新的pcb
err=tcp_bind(tcppcbnew,IP_ADDR_ANY,TCP_SERVER_PORT);//将本地ip与指定的端口号绑定在一起,IP_ADDR_ANY为绑定本地所有的ip地址
tcppcbconn=tcp_listen(tcppcbnew); //设置tcppcb进入监听状态
tcp_accept(tcppcbconn,tcp_server_accept);//初始化lwip的tcp_accpt的回调函数。
httpd_cgi_ssi.c函数分析:
这个函数定义web服务器所存储要显示到http上的内容,定义了SSI的Handler句柄。SSIHandler中需要用到的处理ADC函数、内部温度传感器函数、RTC日期函数、RTCS时间函数。 还定义了CGI_LED/CGI_BEEP的CGI控制句柄。
补充:SSI 和 CGI是什么?
CGI的处理函数运行在服务器端,说白了就是stm32开发板。
浏览器发送uri:通过提交HTML表单的方式来提交请求CGI函数处理的必要信息。
CGI处理函数:当Http服务器收到uri之后,分析它是否是CGI处理结构体中的某个一个函数,如果有的话,就调用处理函数去处理,如果没有,就去寻找其他的网页。(结构体即为static const tCGI ppcURLs[]={{"/leds.cgi",LEDS_CGI_Handler},{"/beep.cgi",BEEP_CGI_Handler},};)
运行过程:
LEDS_CGI_Handler() //CGI_LED控制句柄
->FindCGIParameter() //找到led的索引号
http.c分析:
httpd_init()函数的作用:实现了httpd_ssi_init();httpd_cgi_init();
httpd_init_addr();前两个函数是分别对SSI句柄进行初始化、对CGI进行初始化。对于
CGI在httpd.h中定义了一个CGI的基础文件名(URL),并且关联了如果URL被请求的功能(重点
分析http_cgi_init()函数对CGI句柄的设置):
1、http_set_cgi_handlers(ppcURLs,NUM_CONFIG_CGI_URIS)函数分析:
static const tCGI ppcURLs[]={ //cgi程序
{"/leds.cgi",LEDS_CGI_Handler},
{"/beep.cgi",BEEP_CGI_Handler},
};
即ppcURLs为结构体数组的首地址。NUM_CONFIG_CGI_URIS = 2.
又因为ppcURLs数组的数据类型为tCGI类型。而tCGI类型定义如下:
typedef struct{
const char *pcCGIName; //浏览器请求的URL
tCGIHandler pfnCGIHandler; //定义了一个tcGIHandler指针
}tCGI;
那么可以知道/leds.cgi和/beep.cgi赋值给了pcCGIName,而LEDS_CGI_Handler
和BEEP_CGI_Handler为tCGIHandler类型的函数指针。下面有定义给出:
typedef const char *(*tCGIHandler)(int iIndex, int iNumParams, char *pcParam[],char *pcValue[]);
综上对CGI所述,
即对led和beep两个CGI两个函数名和函数指针赋值给了一个tCGI的结构体。
2、httpd_set_ssi_Handler(SSIHandler,ppcTAGs,NUM_CONFIG_SSI_TAGS)函数分析:
httpd_set_ssi_Handler(tSSIHandler ssi_handler,.....)函数原型定义有:
{
.....
g_pfnSSIHandler = ssi_handler;
g_ppcTags = tags;
g_iNumTags = num_tags;
}
static const char *ppcTAGs[]= //SSI的tag
{
"t", //ADC值
"w", //温度的值
"h", //时间
"y" //日期
};
即ppcTAGs为字符型数组的首地址。NUM_CONFIG_SSI_TAGS = 4.代表4个实验。
g_ppcTags = tags;//将ppcTAGs相当于函数原型中的tags赋给g_ppcTags.
SSIHandler为函数指针,类型为tSSIHandler,定义如下:typedef u16_t (*tSSIHandler)(int iIndex, char *pcInsert, int iInsertLen
#if LWIP_HTTPD_SSI_MULTIPART
, u16_t current_tag_part, u16_t *next_tag_part
#endif /* LWIP_HTTPD_SSI_MULTIPART */
#if LWIP_HTTPD_FILE_STATE
, void *connection_state
#endif /* LWIP_HTTPD_FILE_STATE */
);
即将httpd_cgi_ssi.c中的static u16_t SSIHandler(int iIndex,char *pcInsert,int iInsertLen)函数的函数指针赋给tSSIHandler函数指针。
综上对SSI所述,即
对ADC/RTC/温度等实际上是将它们所在的SSIHandler函数的指针赋给了tSSIHandler类型的结构体。
pcParam中包含了一个URI参数的名称,而pcValue存放了相对应的参数的值,函数返回
URI 统一资源标示符(Uniform Resource Identifier,或URI)是用于标示某一互联网的资源名称的字符串。这种标示允许用户对网络中(一般指万维网)的资源