2023_open_source_contest_preliminary_1st_issue1 from 上海大学_每天学习战队_姚文莹
it is OK
This commit is contained in:
commit
77b6b8cb97
|
@ -126,7 +126,7 @@ ifeq ($(CONFIG_ADD_XIZI_FEATURES),y)
|
|||
endif
|
||||
|
||||
ifeq ($(CONFIG_USER_TEST_WEBSERVER),y)
|
||||
SRC_FILES +=
|
||||
SRC_FILES += test_webserver/test_webserver.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_USER_TEST_MQTTCLIENT),y)
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
# 基于矽璓已实现的Lwip,在ARM上实现基本的Web服务##
|
||||
|
||||
## 1. 简介
|
||||
基于矽璓已实现的Lwip,在ARM上实现基本的Web服务,其功能支持IP、GateWay、DNS、子网掩码等网络参数的设置。
|
||||
主要功能为:web服务等待Http请求的到来,解析Http报文后,设置本机的网络参数信息,在终端打印设置后的网络参数信息,并返回浏览器客户端成功响应。
|
||||
|
||||
## 2. 数据结构设计说明
|
||||
Server的网络结构参数为:
|
||||
```
|
||||
struct ServerNet
|
||||
{
|
||||
char local_ip[20];
|
||||
char local_mask[20];
|
||||
char local_gw[20];
|
||||
char local_dns[20];
|
||||
}ServerNet;
|
||||
```
|
||||
|
||||
主要实现了以下几个函数:
|
||||
```
|
||||
TcpThread: 建立socket监听,循环等待网络通信事件的到来;
|
||||
HandleHttpRequest:处理并解析Http报文,得到网络参数信息;
|
||||
AddrUpdate: 根据到来的参数,更新本机网络参数;
|
||||
LwipShowIP:显示网络参数信息,包括IP、GateWay、DNS、子网掩码;
|
||||
LwipSetIP: 设置网络参数信息,包括IP、GateWay、DNS、子网掩码;
|
||||
ShowDns: 显示dns网址;
|
||||
SetDns: 设置dns网址;
|
||||
```
|
||||
除此之外,还包括两个工具函数:
|
||||
```
|
||||
SubstractServerNet: 截取http报文的请求体,格式为:ip=192.168.1.9&netmask=255.255.255.0&iproute=192.168.1.1&dns=114.114.114.114
|
||||
substring: 截取字符串
|
||||
|
||||
```
|
||||
|
||||
## 3. 测试程序说明
|
||||
1. 通过数据线将开发板连接电脑,并通过网线连接使开发板接入家庭局域网。
|
||||
2. 将TestWebserver注册为shell 命令,编译前通过menuconfig打开lwip和TestWebserver功能。
|
||||
3. 将编译成功的XiZi-edu-arm32.bin文件烧录到arm板子。烧录bin文件前,需要将开发板boot引脚拉高(盖上跳帽),上电后再按下reset按键,之后可以点击烧写工具的执行按钮,等待烧写完成。
|
||||
4. 将boot引脚拉低(摘下跳帽),按下reset按键,使用串口工具显示xiuos的命令行界面。
|
||||
5. 将开发板的本机ip通过setip命令设置为与电脑端在同一个局域网之下,利用ping命令检测成功通信。
|
||||
6. 运行TestWebserver命令验证功能。
|
||||
|
||||
## 4. 运行结果(##需结合运行测试截图按步骤说明##)
|
||||
<img width="800" src="./photos/1.png"/>
|
||||
|
||||
烧录程序,boot引脚拉高,按下reset按键。
|
||||
|
||||
<img width="800" src="./photos/2.png"/>
|
||||
|
||||
点击执行烧录,程序烧录成功。
|
||||
|
||||
<img width="800" src="./photos/3.png"/>
|
||||
|
||||
打开串口调试工具,xiuos程序成功在开发板上运行。
|
||||
|
||||
<img width="800" src="./photos/4.png"/>
|
||||
|
||||
利用setip命令,修改开发板ip,使得开发板和电脑在同一个局域网内,并使用ping命令测试。
|
||||
|
||||
<img width="800" src="./photos/5.png"/>
|
||||
|
||||
在服务端运行TestWebserver命令,打开index.html,设置网络参数信息,点击提交,发送http请求。
|
||||
|
||||
<img width="800" src="./photos/6.png"/>
|
||||
|
||||
web服务收到http请求后并打印post请求报文,以及修改后的开发板的网络参数信息,包括IP、子网掩码、GateWay和DNS。
|
|
@ -0,0 +1,33 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>表单</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!--
|
||||
表单form
|
||||
action:表单提交的位置,可以是网站,也可以是一个请求处理地址
|
||||
method:有post,get提交方式
|
||||
-->
|
||||
<form action="http://192.168.1.5/" method="post">
|
||||
<h2>设置路由信息</h2>
|
||||
|
||||
<!--
|
||||
<input type="text">是文本输入框
|
||||
<input type="password">是密码输入框,默认是用小黑点表示密码的
|
||||
-->
|
||||
<p>IP地址:<input type="text" name="ip"></p>
|
||||
<p>子网掩码:<input type="text" name="netmask"></p>
|
||||
<p>默认网关:<input type="text" name="iproute"></p>
|
||||
<p>DNS服务器<input type="text" name="dns"></p>
|
||||
<p>
|
||||
<input type="submit">
|
||||
<input type="reset">
|
||||
</p>
|
||||
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
Binary file not shown.
After Width: | Height: | Size: 19 MiB |
Binary file not shown.
After Width: | Height: | Size: 180 KiB |
Binary file not shown.
After Width: | Height: | Size: 81 KiB |
Binary file not shown.
After Width: | Height: | Size: 101 KiB |
Binary file not shown.
After Width: | Height: | Size: 52 KiB |
Binary file not shown.
After Width: | Height: | Size: 175 KiB |
|
@ -0,0 +1,218 @@
|
|||
/**
|
||||
* @file: test_webserver.c
|
||||
* @brief: a application of test webserver function
|
||||
* @version: 1.0
|
||||
* @author: Yao wenying
|
||||
* @date: 2023/08/20
|
||||
*/
|
||||
|
||||
|
||||
#include <transform.h>
|
||||
#include "test_webserver.h"
|
||||
|
||||
/**设置ip,网关,子网掩码这部分参考lwip_config_demo.c*/
|
||||
void LwipShowIP()
|
||||
{
|
||||
// find default netdev
|
||||
lw_notice("\r\n************************************************\r\n");
|
||||
lw_notice(" Network Configuration\r\n");
|
||||
lw_notice("************************************************\r\n");
|
||||
lw_notice(" ETH0 IPv4 Address : %u.%u.%u.%u\r\n", ((u8_t*)&lwip_eth0_ipaddr)[0], ((u8_t*)&lwip_eth0_ipaddr)[1],
|
||||
((u8_t*)&lwip_eth0_ipaddr)[2], ((u8_t*)&lwip_eth0_ipaddr)[3]);
|
||||
lw_notice(" ETH0 IPv4 Subnet mask : %u.%u.%u.%u\r\n", ((u8_t*)&lwip_eth0_netmask)[0], ((u8_t*)&lwip_eth0_netmask)[1],
|
||||
((u8_t*)&lwip_eth0_netmask)[2], ((u8_t*)&lwip_eth0_netmask)[3]);
|
||||
lw_notice(" ETH0 IPv4 Gateway : %u.%u.%u.%u\r\n", ((u8_t*)&lwip_gwaddr)[0], ((u8_t*)&lwip_eth0_gwaddr)[1],
|
||||
((u8_t*)&lwip_eth0_gwaddr)[2], ((u8_t*)&lwip_eth0_gwaddr)[3]);
|
||||
lw_notice("************************************************\r\n");
|
||||
}
|
||||
|
||||
uint8_t enet_idd = 0;
|
||||
void LwipSetIP(int argc, char *argv[])
|
||||
{
|
||||
if(argc >= 4)
|
||||
{
|
||||
printf("lw: [%s] ip %s mask %s gw %s netport %s\n", __func__, argv[1], argv[2], argv[3], argv[4]);
|
||||
sscanf(argv[1], "%d.%d.%d.%d", &lwip_ipaddr[0], &lwip_ipaddr[1], &lwip_ipaddr[2], &lwip_ipaddr[3]);
|
||||
sscanf(argv[2], "%d.%d.%d.%d", &lwip_netmask[0], &lwip_netmask[1], &lwip_netmask[2], &lwip_netmask[3]);
|
||||
sscanf(argv[3], "%d.%d.%d.%d", &lwip_gwaddr[0], &lwip_gwaddr[1], &lwip_gwaddr[2], &lwip_gwaddr[3]);
|
||||
sscanf(argv[4], "%d", &enet_idd);
|
||||
|
||||
if(0 == enet_idd)
|
||||
{
|
||||
printf("save eth0 info\n");
|
||||
memcpy(lwip_eth0_ipaddr, lwip_ipaddr, 20);
|
||||
memcpy(lwip_eth0_netmask, lwip_netmask, 20);
|
||||
memcpy(lwip_eth0_gwaddr, lwip_gwaddr, 20);
|
||||
}
|
||||
else if(1 == enet_idd)
|
||||
{
|
||||
printf("save eth1 info\n");
|
||||
memcpy(lwip_eth1_ipaddr, lwip_ipaddr, 20);
|
||||
memcpy(lwip_eth1_netmask, lwip_netmask, 20);
|
||||
memcpy(lwip_eth1_gwaddr, lwip_gwaddr, 20);
|
||||
}
|
||||
}
|
||||
else if(argc == 2)
|
||||
{
|
||||
printf("lw: [%s] set eth0 ipaddr %s \n", __func__, argv[1]);
|
||||
sscanf(argv[1], "%d.%d.%d.%d", &lwip_ipaddr[0], &lwip_ipaddr[1], &lwip_ipaddr[2], &lwip_ipaddr[3]);
|
||||
memcpy(lwip_eth0_ipaddr, lwip_ipaddr, strlen(lwip_ipaddr));
|
||||
}
|
||||
// sys_thread_new("SET ip address", LwipSetIPTask, &enet_id, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO);
|
||||
printf("lw: [%s] config netport id[%d]\n", __func__, enet_idd);
|
||||
lwip_config_net(enet_idd, lwip_ipaddr, lwip_netmask, lwip_gwaddr);
|
||||
}
|
||||
|
||||
void ShowDns(){
|
||||
const ip_addr_t *dns = dns_getserver(0);
|
||||
char *dns_ip = ipaddr_ntoa(dns);
|
||||
printf("lw: eth0 dns is %s \n", dns_ip);
|
||||
}
|
||||
|
||||
void SetDns(char* ip){
|
||||
ip_addr_t dns;
|
||||
ipaddr_aton(ip, &dns);
|
||||
dns_setserver(0, &dns);
|
||||
printf("ETH0 Set DNS Success!\n");
|
||||
}
|
||||
|
||||
void AddrUpdate()
|
||||
{
|
||||
char *argv[5];
|
||||
argv[1] = ServerNet.local_ip;
|
||||
argv[2] = ServerNet.local_mask;
|
||||
argv[3] = ServerNet.local_gw ;
|
||||
argv[4] = 0;
|
||||
LwipSetIP(4, argv);
|
||||
LwipShowIP();
|
||||
SetDns(ServerNet.local_dns);
|
||||
ShowDns();
|
||||
}
|
||||
|
||||
char *substring(char *dst,char *src,int start,int len)
|
||||
{
|
||||
char *p=dst;
|
||||
char *q=src;
|
||||
int length=strlen(src);
|
||||
if(start>=length||start<0)
|
||||
return NULL;
|
||||
if(len>length)
|
||||
len=length-start;
|
||||
q+=start;
|
||||
while(len--)
|
||||
{
|
||||
*(p++)=*(q++);
|
||||
}
|
||||
*(p++)='\0';
|
||||
return dst;
|
||||
}
|
||||
|
||||
void SubstractServerNet(char * params){
|
||||
char *p =params;
|
||||
p +=3;
|
||||
char *end = strchr(p, '&');
|
||||
int len = (int)(end-p);
|
||||
substring(ServerNet.local_ip, p, 0,len);
|
||||
p +=len;
|
||||
p += 9;
|
||||
end = strchr(p, '&');
|
||||
len = (int)(end-p);
|
||||
substring(ServerNet.local_mask , p, 0, len);
|
||||
p +=len;
|
||||
p +=9;
|
||||
end = strchr(p, '&');
|
||||
len = (int)(end-p);
|
||||
substring(ServerNet.local_gw, p, 0, len);
|
||||
p +=len;
|
||||
p += 5;
|
||||
strcpy(ServerNet.local_dns, p);
|
||||
}
|
||||
|
||||
|
||||
void HandleHttpRequest(char *params){
|
||||
SubstractServerNet(params);
|
||||
AddrUpdate(); //修改本机参数信息;
|
||||
}
|
||||
|
||||
//设置socket
|
||||
//循环监听socket并修改网络信息,单线程
|
||||
void tcpecho_thread(){
|
||||
int sock=-1, connected;
|
||||
char *recv_data;
|
||||
struct sockaddr_in server_addr, client_addr;
|
||||
socklen_t sin_size;
|
||||
int recv_data_len;
|
||||
|
||||
recv_data = (char *) malloc(RECV_DATA);
|
||||
|
||||
if(recv_data == NULL){
|
||||
printf("No memory");
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(sock < 0){
|
||||
printf("Socket error\n");
|
||||
goto __exit;
|
||||
}
|
||||
server_addr.sin_family = AF_INET;
|
||||
server_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
server_addr.sin_port = htons(PORT);
|
||||
memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
|
||||
|
||||
if(bind(sock,(struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == 1){
|
||||
printf("Unable to bind\n");
|
||||
goto __exit;
|
||||
}
|
||||
if (listen(sock, 5) == -1)
|
||||
{
|
||||
printf("Listen error\n");
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
while(1){
|
||||
sin_size = sizeof(struct sockaddr_in);
|
||||
connected = accept(sock, (struct sockaddr *)&client_addr, &sin_size);
|
||||
|
||||
printf("new client connected from (%s, %d)\n",
|
||||
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
|
||||
|
||||
{
|
||||
int flag = 1;
|
||||
|
||||
setsockopt(connected,
|
||||
IPPROTO_TCP, /* set option at TCP level */
|
||||
TCP_NODELAY, /* name of option */
|
||||
(void *) &flag, /* the cast is historical cruft */
|
||||
sizeof(int)); /* length of option value */
|
||||
}
|
||||
|
||||
|
||||
recv_data_len = recv(connected, recv_data, RECV_DATA, 0);
|
||||
|
||||
printf("recv %d len data\n",recv_data_len);
|
||||
recv_data[recv_data_len] = '\0';
|
||||
printf("%s\n", recv_data);
|
||||
|
||||
char * params = strstr(recv_data, "ip=");
|
||||
HandleHttpRequest(params);
|
||||
|
||||
char *response = "HTTP/1.1 200 OK\r\n"
|
||||
"Content-Type: application/x-www-form-urlencoded\r\n"
|
||||
"\r\n";
|
||||
write(connected,response,strlen(response));
|
||||
if (connected >= 0)
|
||||
closesocket(connected);
|
||||
|
||||
connected = -1;
|
||||
}
|
||||
__exit:
|
||||
if (sock >= 0) closesocket(sock);
|
||||
if (recv_data) free(recv_data);
|
||||
}
|
||||
|
||||
void TestWebserver(){
|
||||
tcpecho_thread();
|
||||
}
|
||||
|
||||
PRIV_SHELL_CMD_FUNCTION(TestWebserver, Implement web_server, PRIV_SHELL_CMD_MAIN_ATTR);
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* @file: test_webserver.h
|
||||
* @brief: a application of test webserver function
|
||||
* @version: 1.0
|
||||
* @author: Yao wenying
|
||||
* @date: 2023/08/20
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __WEBSERVER_H__
|
||||
#define __WEBSERVER_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include <lwip/sockets.h>
|
||||
#include "lwip/api.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "netif/ethernet.h"
|
||||
#include "lwip/tcpip.h"
|
||||
#include "sys_arch.h"
|
||||
#include <netdev.h>
|
||||
#include "dns.h"
|
||||
#include "string.h"
|
||||
|
||||
|
||||
#define PORT 80
|
||||
#define RECV_DATA 1024
|
||||
struct ServerNet
|
||||
{
|
||||
char local_ip[20];
|
||||
char local_mask[20];
|
||||
char local_gw[20];
|
||||
char local_dns[20];
|
||||
}ServerNet;
|
||||
|
||||
void LwipShowIP();
|
||||
void LwipSetIP(int argc, char *argv[]);
|
||||
void ShowDns();
|
||||
void SetDns();
|
||||
void AddrUpdate(); //更新本机网络参数信息
|
||||
void HandleHttpRequest(); //解析报文,并返回响应
|
||||
void TcpThread();//建立socket监听,循环等待网络通信事件到来
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue