笔者通过w5500实现web服务器点灯

1.http协议概述

HTTP是一个基于请求与响应模式的、无状态的、应用层的协议,常基于TCP的连接方式。

2.http服务器实验设计

笔者用 W5500 建立自己的网页服务器,你只在浏览器地址栏里键入W5500 的 IP 地址,就成功在你的网页上显示出来了。 HTTP Server 实现原理图如下:

3.程序设计

3.1 w5500初始化

分别对w5500进行ip地址的设定、和我们单片机进行spi通信的配置。我们在w5500_conf.c文件中配置好ip地址、子网掩码、网关。要保证ip地址和网关在同一个网段内才能正常通信。再者配置好我们的spi引脚与w5500模块的连接即可完成通信。而

3.2 http server回环测试函数(附解析)

void do_https(void)
{uint8 ch=SOCK_HTTPS;                                                                      /*定义一个socket*/uint16 len;st_http_request *http_request;                                                 /*定义一个结构指针*/memset(rx_buf,0x00,MAX_URI_SIZE);http_request = (st_http_request*)rx_buf;                   /* http service start */switch(getSn_SR(ch))                                                                       /*获取socket状态*/{case SOCK_INIT:                                                                              /*socket处于初始化状态*/listen(ch);break;case SOCK_LISTEN:                                                                         /*socket处于监听状态*/break;case SOCK_ESTABLISHED:                                                                /*socket处于连接状态*/if(getSn_IR(ch) & Sn_IR_CON){setSn_IR(ch, Sn_IR_CON);                                                   /*清除中断标志位*/}if ((len = getSn_RX_RSR(ch)) > 0)       {len = recv(ch, (uint8*)http_request, len);                /*接收http请求*/*(((uint8*)http_request)+len) = 0;proc_http(ch, (uint8*)http_request);                            /*接收http请求并发送http响应*/disconnect(ch);}break;case SOCK_CLOSE_WAIT:                                                            /*socket处于等待关闭状态*/if ((len = getSn_RX_RSR(ch)) > 0){len = recv(ch, (uint8*)http_request, len);             /*接收http请求*/      *(((uint8*)http_request)+len) = 0;proc_http(ch, (uint8*)http_request);                          /*接收http请求并发送http响应*/}disconnect(ch);break;case SOCK_CLOSED:                                                    /*socket处于关闭状态*/socket(ch, Sn_MR_TCP, 80, 0x00);                                    /*打开socket*/break;default:break;}
}

程序解读1:在这里声明一下,调用 do_http() 函数实现 HTTP 服务器,此函数只执行一次,除了reboot_flag==1会重启再重新执行此函数。

/**
*@brief        接收http请求报文并发送http响应,以下这段代码很重要,是http响应阶段
*@param        s: http服务器socket
*@param        buf:解析报文内容
*@return   无
*/
void proc_http(SOCKET s, uint8 * buf)
{int8* name;                                            int8 req_name[32]={0x00,};                                                         /*定义一个http响应报文的指针*/unsigned long file_len=0;                                                               /*定义http请求报文头的结构体指针*/uint16 send_len=0;uint8* http_response;st_http_request *http_request;memset(tx_buf,0x00,MAX_URI_SIZE);http_response = (uint8*)rx_buf;http_request = (st_http_request*)tx_buf;parse_http_request(http_request, buf);                             /*解析http请求报文头*/switch (http_request->METHOD)     {case METHOD_ERR :                                                                          /*请求报文头错误*/memcpy(http_response, ERROR_REQUEST_PAGE, sizeof(ERROR_REQUEST_PAGE));send(s, (uint8 *)http_response, strlen((int8 const*)http_response));break;case METHOD_HEAD:                                                                            /*HEAD请求方式*/case METHOD_GET:                                                                            /*GET请求方式*/name = http_request->URI;if(strcmp(name,"/index.htm")==0 || strcmp(name,"/")==0 || (strcmp(name,"/index.html")==0)){file_len = strlen(INDEX_HTML);make_http_response_head((uint8*)http_response, PTYPE_HTML,file_len);send(s,http_response,strlen((char const*)http_response));send_len=0;while(file_len){if(file_len>1024){if(getSn_SR(s)!=SOCK_ESTABLISHED){return;}send(s, (uint8 *)INDEX_HTML+send_len, 1024);send_len+=1024;file_len-=1024;}else{send(s, (uint8 *)INDEX_HTML+send_len, file_len);send_len+=file_len;file_len-=file_len;} }}else if(strcmp(name,"/w5500.js")==0){memset(tx_buf,0,MAX_URI_SIZE);make_basic_config_setting_json_callback(tx_buf,CONTROLH);sprintf((char *)http_response,"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length:%d\r\n\r\n%s",strlen(tx_buf),tx_buf);send(s, (u_char *)http_response, strlen((char const*)http_response));}break;case METHOD_POST:                                                                           /*POST请求*/mid(http_request->URI, "/", " ", req_name);                    /*获取该请求的文件名*/if(strcmp(req_name,"config.cgi")==0)                               {cgi_ipconfig(http_request);                                                /*将配置信息写进单片机eeprom*/make_cgi_response(5,(int8*)ConfigMsg.lip,tx_buf);   /*生成响应的文本部分*/        sprintf((char *)http_response,"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length:%d\r\n\r\n%s",strlen(tx_buf),tx_buf);/*发送http响应*/send(s, (u_char *)http_response, strlen((char *)http_response));        disconnect(s);                                                                      /*断开socket连接*/              reboot_flag=1;                                                                     /*重启标志位置1*/return;}break;default :break;}
}
/**
*@brief        功能函数,可以配置读取到的值以驱动单片机
*@param        http_request:定义一个http请求的结构体指针
*@return   无
*/
void cgi_ipconfig(st_http_request *http_request)
{ uint8 * param;param = get_http_param_value(http_request->URI,"room");       /*房间号,其实笔者是点亮LED1,读者可以对代码进行优化*/if(param){LED1_ON; }param = get_http_param_value(http_request->URI,"leftroom");      /*获取需要关灯的房号,笔者没配置,读者可优化*/if(param){}param = get_http_param_value(http_request->URI,"a");    /*获取修改后的a,这里我没配置*/if(param){}
}
/*以下是笔者设计的网页*/
#ifndef __WEBPAGE_H
#define __WEBPAGE_H
#define INDEX_HTML  "<!DOCTYPE html>"\
"<html>"\
"<head>"\
"<title>室内各电器配置—小兵科技</title>"\
"<meta http-equiv='Content-Type' content='text/html; charset=GB2312'/>"\
"<style type='text/css'>"\
"body {text-align:left; background-color:#c0deed;font-family:Verdana;}"\
"#main {margin-right:auto;margin-left:auto;margin-top:30px;}"\
"label{display:inline-block;width:150px;}"\
"#main h3{color:#66b3ff; text-decoration:underline;}"\
"</style>"\
"<script>"\
"function $(id) { return document.getElementById(id); };"\
"function settingsCallback(o) {"\
"if ($('txtPub')) $('txtPub').value = 100;"\
"if ($('txtRoom')) $('txtRoom').value = o.room;"\
"if ($('txtLeftroom')) $('txtLeftroom').value = o.ip;"\
"if ($('txtA')) $('txt').value = o.sub;"\
"if ($('txtB')) $('txtB').value = o.gw;"\
"};"\
"</script>"\
"</head>"\
"<body>"\
"<div id='main'>"\
"<div style='background:snow; display:block;padding:10px 20px;'>"\
"<h3>小彬科技智能家居</h3>"\
"<form id='frmSetting' method='POST' action='config.cgi'>"\
"<p><label for='txtPub'>版本号:</label><input type='text' id='txtPub' name='pub' size='16' disabled='disabled' /></p>"\
"<p><label for='txtRoom'>点亮的灯(输入1到7房间号):</label><input type='text' id='txtRoom' name='room' size='16' /></p>"\
"<p><label for='txtLeftroom'>关掉哪个灯(输入1到7房间号):</label><input type='text' id='txtLeftroom' name='leftroom' size='16' /></p>"\
"<p><label for='txtA'>未开发功能:</label><input type='text' id='txtA' name='a' size='16' /></p>"\
"<p><label for='txtB'>未开放功能:</label><input type='text' id='txtB' name='b' size='16' /></p>"\
"<p><input type='submit' value='确认并执行' /></p>"\
"</form>"\
"</div>"\
"</div>"\
"<div style='margin:5px 5px;'>"\
"&copy;Copyright 2021 by 清风芝明"\
"</div>"\
"<script type='text/javascript' src='w5500.js'></script>"\
"</body>"\
"</html>"#endif

3.3主函数

#include <stdio.h>
#include <string.h>
#include "stm32f10x.h"
#include "bsp_usart1.h"
#include "bsp_i2c_ee.h"
#include "bsp_i2c_gpio.h"
#include "bsp_led.h"

#include "w5500.h"
#include "W5500_conf.h"
#include "socket.h"
#include "utility.h"

/*app函数头文件*/
#include "http_server.h"
#include "httputil.h"

uint8 reboot_flag = 0;
int main(void)
{     
    
    systick_init(72);                                        /*初始化Systick工作时钟*/
    USART1_Config();                                        /*初始化串口通信:115200@8-n-1*/
    i2c_CfgGpio();                                            /*初始化eeprom*/
    LED_GPIO_Config();              //笔者点灯,所以初始化,读者想增加更多功能也可增加初始化...
    printf("  网络初始化 Demo V1.0 \r\n");

gpio_for_w5500_config();                                /*初始化MCU相关引脚*/
    reset_w5500();                                            /*硬复位W5500*/
    set_w5500_mac();                                        /*配置MAC地址*/
    set_w5500_ip();                                            /*配置IP地址*/
    
    socket_buf_init(txsize, rxsize);        /*初始化8个Socket的发送接收缓存大小*/
    
    printf(" 应用程序执行中…… \r\n"); 
    printf(" 在IE浏览器中输入 W5500的IP就可访问web Server \r\n");
  
    while(1)                                                         /*循环执行的函数*/ 
    {
    do_https();/*Web server测试程序*/
//    if(reboot_flag==1)
//   reboot();
    }
}

4.成果演示

在点亮的灯处输入1

点击确认并执行之后的现象

笔者的代码应该还有更多值得优化的地方,这应该也算是一个应用,不过存在一些缺陷,点完灯之后需要手动去复位开发板以熄灭灯等等,可以后续进行优化。通过编写网页也更加深刻理解http的响应机制,也是具有不错的收获,读者也可以试着自己改写一个网页。

W5500 充当http server - web服务器的实现相关推荐

  1. WEB服务器和HTTP服务器(http server)和应用服务器的区别?(web服务器就是HTTP服务器)为什么要把Web服务器独立配置,和应用程序服务器一前一后?

    参考文章1:WEB服务器.应用程序服务器.HTTP服务器区别 参考文章2:如何区分Web服务器.HTTP服务器.应用程序服务器 WEB服务器.应用程序服务器.HTTP服务器有何区别?IIS.Apach ...

  2. [golang Web开发] 1.golang web开发:简介以及web服务器的搭建以及http协议简介

    一.web开发简介 1.简介 Web应用在我们的生活中无处不在,看看我们日常使用的各个应用程序,它们要么是 Web应用,要么是移动 App 这类 web应用的变种,无论哪一种编程语言,只要它能够开发出 ...

  3. 使用 Fail2ban 保护 Web 服务器免受 DDoS 攻击

    任何暴露于公共互联网的服务端点都容易受到黑客的大量攻击.您的服务可能是网站.API 端点或任何其他应用程序层服务.恶意用户和机器人将通过重复发送更高频率的请求来尝试侵入您的系统.在这篇文章中,我将向您 ...

  4. 无法连接到已配置的开发web服务器_你知道多少种服务器?这三种服务器你都认识吗?...

    服务器是现实中常被讨论的设备之一,因为服务器与现代生活息息相关.按照服务器的用途,服务器可细分为诸多类别.为增进大家对服务器的了解程度,本文将对三种服务器予以介绍,它们分别是:Web服务器.应用程序服 ...

  5. WEB服务器和HTTP服务器和应用服务器的区别?(web服务器就是HTTP服务器)为什么要把Web服务器独立配置,和应用程序服务器一前一后?

    参考文章1:WEB服务器.应用程序服务器.HTTP服务器区别 参考文章2:如何区分Web服务器.HTTP服务器.应用程序服务器 WEB服务器.应用程序服务器.HTTP服务器有何区别?IIS.Apach ...

  6. web服务器与APP服务器

    web服务器与APP服务器 通俗的讲,Web服务器传送(serves)页面使浏览器可以浏览,然而应用程序服务器提供的是客户端应用程序可以调用(call)的方法(methods).确切一点,你可以说:W ...

  7. 理清web服务器跟应用服务器的基本概念(纯拷贝)

    一 常见的WEB服务器和应用服务器 在UNIX和LINUX平台下使用最广泛的免费web服务器是W3C.NCSA和APACHE服务器,而Windows平台NT/2000/2003使用IIS的WEB服务器 ...

  8. 景安服务器怎么上传网站程序,Web服务器是如何被应用服务器“收编”的?

    在传统 Web 应用的多层架构中 系统一般会包括有负载均衡器 Web 服务器.应用服务器等多个后端服务 其中,Web 服务器和应用服务器 常常被人视为一个整体 但其实从工作原理上来说 两者还是有一定区 ...

  9. Web服务器和应用服务器有啥区别?

    转自:微点阅读  https://www.weidianyuedu.com Web服务器和应用服务器简介 通俗的讲,Web服务器传送页面使浏览器可以浏览,然而应用程序服务器提供的是客户端应用程序可以调 ...

最新文章

  1. 关于group by 和having(数据库)
  2. 需要监控JanusGraph的一些指标
  3. 推荐算法注意点和DeepFM工程化实现
  4. jps,jstat,jinfo,jmap,jhat,jstack工具的使用/查看Linux磁盘信息
  5. linux命令(7)—— 管道符|、ps
  6. 数论--费马小定理求逆元
  7. html判断是安卓还是苹果手机,网页能够自己判断是pc端首页还是手机android和苹果。...
  8. python process返回值_如何恢复传递给multiprocessing.Process的函数的返回值?
  9. 力扣190.颠倒二进制数
  10. java中hashmap_Java HashMap – Java中的HashMap
  11. 建议收藏,10个Windows系统装机必备软件,相见恨晚!
  12. 教你查看sql server 2000 sp4补丁是否安装成功 (安装补丁后可以远程访问)
  13. 2018黑马java简历模板_2018黑马软件测试
  14. 人脸及指纹双重识别门禁系统
  15. SLA 、SLO SLI
  16. matlab 矩阵分行标准化,matlab如何将矩阵标准化 命令是什么?
  17. 美赛数模论文之表的格式
  18. 保研面试复习之计算机网络篇
  19. 【C#】EAN-13条形码生成与识别
  20. Paper之CVPRICCVECCV:2009年~2019年CVPRICCVECCV(国际计算机视觉与模式识别会议国际计算机视觉大会欧洲计算机视觉会议)历年最佳论文简介及其解读

热门文章

  1. linux系统调用及错误处理
  2. 分数短语作主语,谓语的形式
  3. python人脸姿态_(原)人脸姿态识别Fine-Grained Head Pose EstimationWithout Keypoints
  4. 这平原是我走不出去的大山
  5. 存储介质中ext4的文件排布
  6. idea springboot activities集成第一步
  7. I2S/(PCM/TDM)/AC97/PDM区别(二十)
  8. 校园网络视频直播的重要性,实现高效智慧教育
  9. 关于晋升全栈工程师,从入门到放弃的神功秘籍,不点进来看一看?
  10. Androi--Linux下的常用命令行