嵌入式 lwip http server makefsdata

背景:

基于君正X2000 MCU Freertos+lwip架构 实现HTTP server服务,MCU作为HTTP服务器通过网口进行数据包的传输,提供网页服务。其中设计到LWIP提供的工具makefsdata,常用于将文件或目录结构转换为适合嵌入到固件中的二进制格式。

一、 lwip 源码和资源

1. 1 源码资源下载链接

lwip官方网站:https://savannah.nongnu.org/projects/lwip/

lwip官方网站下载地址:https://download.savannah.nongnu.org/releases/lwip/

下载解压打开后文件目录大致是这个样子

1.2 资源目录介绍:

fs用于存放网页资源诸如HTML、CSS、JavaScript等文件。makefsdata是官网提供的工具用于将fs中网页资源转换为适合嵌入到固件中的二进制格式,使用makefsdata生成fsdata.c方便集成到嵌入式系统当中。其他是一些http实现的接口及头文件。

二 、makefsdata工具使用

2.1 makefsdata转换工具有俩种实现方式:

2. 1. 1使用makefsdata脚本

使用源码makefsdata文件夹下的makefsdata脚本直接解释运行,使用脚本只需要添加运行权限,直接运行即可快捷方便的生成fsdata.c集成到嵌入式系统中。但是缺乏一些扩展功能,使用不够灵活且无法使用压缩,这对于资源有限的嵌入式设备来说是不可接受的。

lwip源码资源下载后存放网页资源的fs脚本在makefsdata脚本的上层目录,而makefsdata脚本默认将当前目录下的文件资源转换生成fsdata.c。故对脚本做一些修改。将脚本中的chdir("fs"); ------> chdir(".../fs");

添加文件复制移动命令将生成的fsdata.c自动替换成上层旧文件方便生成后编译

下面是修改后的完整makefsdata脚本

c 复制代码
#!/usr/bin/perl

use File::Copy;

open(OUTPUT, "> fsdata.c");

chdir("../fs");
open(FILES, "find . -type f |");

while($file = <FILES>) {

    # Do not include files in CVS directories nor backup files.
    if($file =~ /(CVS|~)/) {
    	next;
    }
    
    chop($file);
    
    open(HEADER, "> /tmp/header") || die $!;
    if($file =~ /404/) {
	print(HEADER "HTTP/1.0 404 File not found\r\n");
    } else {
	print(HEADER "HTTP/1.0 200 OK\r\n");
    }
    print(HEADER "Server: lwIP/pre-0.6 (http://www.sics.se/~adam/lwip/)\r\n");
    if($file =~ /\.html$/) {
	print(HEADER "Content-type: text/html\r\n");
    } elsif($file =~ /\.gif$/) {
	print(HEADER "Content-type: image/gif\r\n");
    } elsif($file =~ /\.png$/) {
	print(HEADER "Content-type: image/png\r\n");
    } elsif($file =~ /\.jpg$/) {
	print(HEADER "Content-type: image/jpeg\r\n");
    } elsif($file =~ /\.class$/) {
	print(HEADER "Content-type: application/octet-stream\r\n");
    } elsif($file =~ /\.ram$/) {
	print(HEADER "Content-type: audio/x-pn-realaudio\r\n");    
    } else {
	print(HEADER "Content-type: text/plain\r\n");
    }
    print(HEADER "\r\n");
    close(HEADER);

    unless($file =~ /\.plain$/ || $file =~ /cgi/) {
	system("cat /tmp/header $file > /tmp/file");
    } else {
	system("cp $file /tmp/file");
    }
    
    open(FILE, "/tmp/file");
    unlink("/tmp/file");
    unlink("/tmp/header");

    $file =~ s/\.//;
    $fvar = $file;
    $fvar =~ s-/-_-g;
    $fvar =~ s-\.-_-g;
    print(OUTPUT "static const unsigned char data".$fvar."[] = {\n");
    print(OUTPUT "\t/* $file */\n\t");
    for($j = 0; $j < length($file); $j++) {
	printf(OUTPUT "%#02x, ", unpack("C", substr($file, $j, 1)));
    }
    printf(OUTPUT "0,\n");
    
    
    $i = 0;
    while(read(FILE, $data, 1)) {
        if($i == 0) {
            print(OUTPUT "\t");
        }
        printf(OUTPUT "%#02x, ", unpack("C", $data));
        $i++;
        if($i == 10) {
            print(OUTPUT "\n");
            $i = 0;
        }
    }
    print(OUTPUT "};\n\n");
    close(FILE);
    push(@fvars, $fvar);
    push(@files, $file);
}

for($i = 0; $i < @fvars; $i++) {
    $file = $files[$i];
    $fvar = $fvars[$i];

    if($i == 0) {
        $prevfile = "NULL";
    } else {
        $prevfile = "file" . $fvars[$i - 1];
    }
    print(OUTPUT "const struct fsdata_file file".$fvar."[] = {{$prevfile, data$fvar, ");
    print(OUTPUT "data$fvar + ". (length($file) + 1) .", ");
    print(OUTPUT "sizeof(data$fvar) - ". (length($file) + 1) .", FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT}};\n\n");
}

chdir("../makefsdata");
move("fsdata.c", "../fsdata.c");

print(OUTPUT "#define FS_ROOT file$fvars[$i - 1]\n\n");
print(OUTPUT "#define FS_NUMFILES $i\n");

2.1.2 编译makefsdata.c后使用可执行文件生成fsdata.c

博主在windows下使用vscode+mingw编译生成makefsdata.exe,进而使用该程序生成fsdata.c。相较于脚本使用多了一步编译生成的步骤,但是多了许多扩展功能且可以进行zlib压缩网页资源文件。对于资源有限的嵌入式设备压缩功能就十分必要。编译好的makefsdata.exe放在置顶,可以直接在windows下命令行运行。

编译参考博客 使用vscode编译makefsdata 如果需要压缩功能需要额外下载第三方库如zlip。压缩转换命令如下,可配合-XC排除不需要压缩的文件。官网提供的网页资源不经压缩转换后fsdata.c大小为21KB,经过-defl:5参数压缩转换后为14KB。压缩比例约为66KB,不同压缩等级,网页资源经过压缩后压缩比例不尽相同。

c 复制代码
makefsdata.exe -defl:5   //  Windows下命令行运行,-defl表示使用压缩,5表示压缩等级(1-10)默认10

扩展功能参考资源文件下的readme.txt,更多功能可以参考源码或者makefsdata -help查看user page。

c 复制代码
This directory contains a script ('makefsdata') to create C code suitable for
httpd for given html pages (or other files) in a directory.

There is also a plain C console application doing the same and extended a bit.

Usage: htmlgen [targetdir] [-s] [-i]s
   targetdir: relative or absolute path to files to convert
   switch -s: toggle processing of subdirectories (default is on)
   switch -e: exclude HTTP header from file (header is created at runtime, default is on)
   switch -11: include HTTP 1.1 header (1.0 is default)

  if targetdir not specified, makefsdata will attempt to
  process files in subdirectory 'fs'.

The C version of this program can optionally store the none-SSI files in
a compressed form in which they are also sent to the web client (which
must support the Deflate content encoding). Files that grow during compression
(due to being not compressible well), will stored umcompressed automatically.
In order to do so, compile the program with MAKEFS_SUPPORT_DEFLATE set to 1. You must
manually download minizip.c for this to work. As an alternative, you can additionally
define MAKEFS_SUPPORT_DEFLATE_ZLIB to use your system's zlib instead.
Compression of .html, .js, .css and .svg files usually yields very good compression
rates and is a great way of reducing your program's size.

makefsdata.c实现的扩展功能。

c 复制代码
static void print_usage(void)
{
  printf(" Usage: htmlgen [targetdir] [-s] [-e] [-11] [-nossi] [-ssi:<filename>] [-c] [-f:<filename>] [-m] [-svr:<name>] [-x:<ext_list>] [-xc:<ext_list>" USAGE_ARG_DEFLATE NEWLINE NEWLINE);
  printf("   targetdir: relative or absolute path to files to convert" NEWLINE);
  printf("   switch -s: toggle processing of subdirectories (default is on)" NEWLINE);
  printf("   switch -e: exclude HTTP header from file (header is created at runtime, default is off)" NEWLINE);
  printf("   switch -11: include HTTP 1.1 header (1.0 is default)" NEWLINE);
  printf("   switch -nossi: no support for SSI (cannot calculate Content-Length for SSI)" NEWLINE);
  printf("   switch -ssi: ssi filename (ssi support controlled by file list, not by extension)" NEWLINE);
  printf("   switch -c: precalculate checksums for all pages (default is off)" NEWLINE);
  printf("   switch -f: target filename (default is \"fsdata.c\")" NEWLINE);
  printf("   switch -m: include \"Last-Modified\" header based on file time" NEWLINE);
  printf("   switch -svr: server identifier sent in HTTP response header ('Server' field)" NEWLINE);
  printf("   switch -x: comma separated list of extensions of files to exclude (e.g., -x:json,txt)" NEWLINE);
  printf("   switch -xc: comma separated list of extensions of files to not compress (e.g., -xc:mp3,jpg)" NEWLINE);
#if MAKEFS_SUPPORT_DEFLATE
  printf("   switch -defl: deflate-compress all non-SSI files (with opt. compr.-level, default=10)" NEWLINE);
  printf("                 ATTENTION: browser has to support \"Content-Encoding: deflate\"!" NEWLINE);
#endif
  printf("   if targetdir not specified, htmlgen will attempt to" NEWLINE);
  printf("   process files in subdirectory 'fs'" NEWLINE);
}

三、集成fsdata.c到嵌入式设备

3.1 概述:君正X2000芯片提供2个网口驱动,不同芯片架构平台网口实现大同小异不是本文核心内容不做赘述。本次实验将设备默认静态IP设置为192.168.3.120。将生成的fsdata.c替换后编译生成固件烧录至开发板后即可展示网页资源。

3.2 调用LWIP实现HTTP server

调用LWIP实现最基础的网页展示十分简单,只需要将生成fsdata.c替换后在主程序头部包含LWIP头文件

c 复制代码
#include "lwip/apps/httpd.h"

在主程序中调用httpd_init即可启动http server。

c 复制代码
httpd_init();		// 初始化 HTTPD SERVER

嵌入式设备通过网线连接到PC,打开浏览器输入192.168.3.120(端口号会默认80)即可展示网页资源左上角图片为替换验证后的图片资源(与LWIP官方提供的默认图片资源不一样)。

3.3 http server实际应用功能待更新。。。

相关推荐
巴巴_羊2 小时前
前端面经 计网 http和https区别
网络协议·http·https
LyaJpunov5 小时前
HTTPS全解析:从证书签发到TLS握手优化
网络协议·http·https
你曾经是少年5 小时前
HTTPS
网络协议·http·https
2501_915918415 小时前
多账号管理与自动化中的浏览器指纹对抗方案
websocket·网络协议·tcp/ip·http·网络安全·https·udp
忧虑的乌龟蛋6 小时前
嵌入式Linux I2C驱动开发详解
linux·驱动开发·嵌入式·iic·i2c·读数据·写数据
-九斤-9 小时前
http和https的区别
网络协议·http·https
whoarethenext9 小时前
https的发展历程
网络协议·http·https
摸鱼仙人~9 小时前
HTTP 响应状态码总结
网络·网络协议·http
Suckerbin9 小时前
基于HTTP头部字段的SQL注入:SQLi-labs第17-20关
网络·笔记·网络协议·安全·http·网络安全
张一不吃豆芽13 小时前
TCPIP详解 卷1协议 八 ICMPv4和ICMPv6 Internet控制报文协议
网络·网络协议·tcp/ip