2023_open_source_contest_preliminary_1st_issue1 from 上海大学_每天学习战队_姚文莹

it is OK
This commit is contained in:
IACU 2023-10-23 14:20:25 +08:00
commit 77b6b8cb97
11 changed files with 362 additions and 1 deletions

View File

@ -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)

View File

@ -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。

View File

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>表单</title>
</head>
<body>
<!--
表单form
action表单提交的位置可以是网站也可以是一个请求处理地址
method有postget提交方式
-->
<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

View File

@ -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);

View File

@ -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