你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

uIP WebServer 实现

[复制链接]
咕噜 发布时间:2015-4-19 18:08
本帖最后由 咕噜 于 2015-4-19 18:25 编辑 6 ]% V% u' Y6 j, u" G

8 v$ ~2 y4 {; B1 t4 j5 q8 s. {原帖地址) H+ B$ D' G6 \9 a, K, k
http://www.ichanging.org/uip-webserver.html2 y7 U- ^1 m" O" d" ~
这篇帖子写的不错,分享一下。对于理解uIP很有帮助。
; W. f$ u, C# h; V! f9 x0 u% E- }Uip的Webserver比较复杂,用c语言实现一个简单服务器的所有功能,路由功能,GET传参,动态页面生成等。
0 w% n, U$ c+ {) \: l; P
要运行Uip的WebServer 只需要:
( X0 p# {% G, F. j% }5 M3 R1. 修改uip-con.h 里的#inlcude "webserver.h"  去除其注释3 _) S* h/ }0 v& A
2. 在User/main.c 里加入      httpd_init();   //初始化服务器- w. w' i/ L, C9 V- N
Uip+ stm32移植参见 Uip + Stm32移植问题总结 , T. T+ o; k& c2 B, i
浏览器访问 Uip WebServer 页面:. n1 J8 e) X. E9 t8 k7 |) e
$ y: d3 q% j5 C6 E6 Z1 |
分析下 Uip Webserver 的运行过程,Uip WebServer使用到相关文件如下:
/ G8 J) n% m1 g; Q5 ?
' ~9 [- B$ P; N8 a  rhttpd.c                        
5 ]1 L7 a& o. L9 x7 ^httpd.c中定义了一些ASCII码,含义如下+ n" W( `' E  V3 a
  1. #define ISO_nl      0x0a     // 换行# P' Q* x! O# K! w! n
  2. #define ISO_space   0x20     // 空格2 Z, O" [* i7 a8 m
  3. #define ISO_bang    0x21     // !. f# r0 a1 T. o
  4. #define ISO_percent 0x25     // %
    ) [/ u2 z2 @  @
  5. #define ISO_period  0x2e     // .
    7 ]3 X0 ~. [* y" \
  6. #define ISO_slash   0x2f     // /7 H6 `& u! U$ n4 ?
  7. #define ISO_colon   0x3a     // :
复制代码

/ }; o& F9 Y7 i3 U# S当Uip接收到Uip接收到底层传递的数据,将接收到的数据通过调用http_appcall(),传递给Webserver处理,再通过handle_connection()先后调用handle_input()函数和handle_output()函数- ~2 Z  Y0 z  v; P
handle_input()主要作用是分析http数据流:' F6 k8 I0 }: j4 j

) m" ^0 n3 X( S1 K& L- p* l
  1. static  PT_THREAD(handle_input(struct httpd_state *s))      //分析http数据流, http数据流格式(eg. "GET /6?user=123 HTTP/ ...")# `2 B2 M" |$ A# a) T2 t; F- G, q
  2. {
    & G8 e' \5 h! ]& X
  3.   char * ptr;0 U3 M4 T5 B  J. F6 W2 K
  4. $ I0 [+ q0 v' B" N6 m
  5.   PSOCK_BEGIN(&s->sin);
    0 f! K8 \5 @6 N
  6. ) |' o) |/ C" A) @: o
  7.   //取出到下一个空格号之前的数据
    & o( L) V! M% b- W
  8.   PSOCK_READTO(&s->sin, ISO_space);                 //Uip使用这个函数从http数据流中剥离数据
    0 ^4 f0 D6 A3 q0 Y3 o, j

  9. 5 Y8 T# P+ J, a. P& l/ U+ t. S
  10.    
    % I1 G% Z% Z% [2 w4 \: q4 B9 D
  11.   if(strncmp(s->inputbuf, http_get, 4) != 0) {             //判断数据流前4位字符是否为"GET ",判断是否为GET传参
    7 {. J1 F7 o) m4 ?" S
  12.     PSOCK_CLOSE_EXIT(&s->sin);
    2 `, n! R. B  l' x4 J: A/ [* z: p
  13.   }
    1 q$ W' m0 `: k5 S2 c7 L

  14. ! C5 I* _6 H) Q' @/ u+ O
  15.   PSOCK_READTO(&s->sin, ISO_space);
    7 p& V  Y5 v$ T% l$ w

  16. 5 |9 o: v" R3 @% B0 f9 t* E  z. E4 _* g
  17.   if(s->inputbuf[0] != ISO_slash) {                ; f% i% t3 L. ~6 C0 G5 e8 P0 D. f& F
  18.     PSOCK_CLOSE_EXIT(&s->sin);
    3 W" a; u* R2 G0 r6 \# B5 \
  19.   }
    & r+ w" L& j5 j# v
  20. 7 c/ A' ~+ j7 i% @
  21.   if(s->inputbuf[1] == ISO_space) {                   //请求路径为 "/ " (eg. 192.168.1.15/ ) 更新请求页面filename 为/index.html5 `8 \/ `2 i- Q4 |
  22.     strncpy(s->filename, http_index_html, sizeof(s->filename));
    / L$ C2 I8 W3 Z6 |$ q* D7 T
  23.   } else {                                        //根据请求路径,更新结构体中filename为相应页面名称- i2 Y0 c9 e/ N6 e7 R5 u
  24.     s->inputbuf[PSOCK_DATALEN(&s->sin) - 1] = 0;$ o% h! f) o8 ~" h: d
  25.     strncpy(s->filename, &s->inputbuf[0], sizeof(s->filename));         Z* w6 g1 [1 |
  26.   }  z8 m0 c  v' \0 b  \' {
  27. * O" i( r  C# _) Z* m
  28.   /*  httpd_log_file(uip_conn->ripaddr, s->filename);*/; i- G& l. k  y3 Z
  29.    
    . L6 m) L4 j4 A8 Q, L/ n8 J+ P
  30.   s->state = STATE_OUTPUT;
    : }1 n( [: Z6 X

  31. + f) o+ E6 z' z/ H3 m
  32.   while(1) {1 r% F7 d* l0 F$ n/ u4 P
  33.     PSOCK_READTO(&s->sin, ISO_nl);
    * h8 q$ ?+ [+ W) f! B

  34. % D' V; G; W* Z4 H8 k8 w
  35.     if(strncmp(s->inputbuf, http_referer, 8) == 0) {# [. ]% x2 X2 M! c, Z
  36.       s->inputbuf[PSOCK_DATALEN(&s->sin) - 2] = 0;3 |) J( u( b  @" \; k
  37.       /*      httpd_log(&s->inputbuf[9]);*/3 h( Z3 J4 Z' {
  38.     }, e  d; t9 I" L
  39.   }. ~5 n7 L, \, j; W8 q3 \
  40.    
    - X9 [* }9 a& C4 {
  41.   PSOCK_END(&s->sin);
    $ ]+ ^9 `# {) _, |
  42. }
复制代码
分析数据得出访问页面的名字,存入一个全局的结构体中,handle_output()函数根据这个结构体获得要输出的页面名字,做相应处理:) Y- n& s( U- j8 L) i$ _
  1. static PT_THREAD(handle_output(struct httpd_state *s))
    ' Z% P, R2 K% D4 j+ Y+ ]
  2. {0 B7 p# j6 \9 `/ D! ]
  3.   char *ptr;  x3 g5 l. @( C0 m3 k# I6 ?
  4.    ) @3 `) m( ]% g2 K2 r
  5.   PT_BEGIN(&s->outputpt);* v' \) Y3 N8 c) `" {/ L- N# A
  6.   
    : [. @- a1 \( G. d/ _! d' Q
  7.   if(!httpd_fs_open(s->filename, &s->file)) {          //没有此页面,打开404页面
    " R7 N5 I1 y! k/ W9 c; W
  8.     httpd_fs_open(http_404_html, &s->file);
    8 r% R% g4 ?& S" B# E. [. j
  9.     strcpy(s->filename, http_404_html);. ^7 b0 B1 `& t
  10.     PT_WAIT_THREAD(&s->outputpt,
    3 X1 U$ K0 n- g. ?" q
  11.            send_headers(s,  f; @: Q( q) ?
  12.            http_header_404));5 B6 H% s: z4 Z8 N; n
  13.     PT_WAIT_THREAD(&s->outputpt,+ {, ^- g) w9 f! `
  14.            send_file(s));. q, y1 M1 q8 a
  15.   } else {                               //正常打印相应页面
    2 E" u! n( K  a) P
  16.     PT_WAIT_THREAD(&s->outputpt,                      2 i3 e7 m6 Q2 L8 W
  17.            send_headers(s,
      O9 J: i7 K" ^* u  X
  18.            http_header_200));
    6 b: d1 _6 M+ W' t
  19.     ptr = strchr(s->filename, ISO_period);               //查找字符串s->filename中首次出现字符ISO_period的位置,返回首次出现c的位置的指针8 w8 K! \' j9 I  @- s3 u3 K4 p% Y- F
  20.     if(ptr != NULL && strncmp(ptr, http_shtml, 6) == 0) {    //判断是否为 .shtml网页文件   
    8 ^9 i$ P" l2 E  G$ m- \
  21.       PT_INIT(&s->scriptpt);
    * S' s# D* ?8 `5 F
  22.       PT_WAIT_THREAD(&s->outputpt, handle_script(s));    //若为 .shtml页面,则调用handle_script()生成动态网页
    2 w8 @2 d& P, E
  23.     } else {                            //不是 .shtml(eg.  /index.html),输出该页面数据$ W& u$ E" |9 C( M0 d8 j' X# {
  24.       PT_WAIT_THREAD(&s->outputpt,
    ! z9 |" d: Y, ]4 E
  25.              send_file(s));. f- b, O/ u2 X, J4 f. c3 s# {
  26.     }0 R7 h  Y! X) [2 W' E
  27.   }7 Y7 p6 h' k2 Z
  28.   PSOCK_CLOSE(&s->sout);/ Z2 m6 @( g6 n- G$ Z& V! D- A  {) b& F' }
  29.   PT_END(&s->outputpt);
    1 q- ~1 R( ^! ~# [' S
  30. }
复制代码

- G( h# `5 f2 ~3 ^9 F1 n
httpd_fs_open()定义于httpd-fs.c,用于读取相应页面的数据,将页面数据存入全局结构体中,是实现路由遍历的关键函数:" D" v- a) M% y+ _% ]# X) f9 l* m( K
  1. int  httpd_fs_open(const char *name, struct httpd_fs_file *file)
    ; h$ ^0 U, L0 u- x+ s' @( `9 J9 w9 m
  2. {
    1 u: D: I& E" y5 S8 L; c. Q, b
  3. #if HTTPD_FS_STATISTICS
    8 g) n9 P4 {( L0 y4 M6 z/ q
  4.   u16_t i = 0;/ V, U1 i& X8 u7 T9 {
  5. #endif /* HTTPD_FS_STATISTICS */
    ) T* B  K; }! J8 N. j6 d/ w
  6.   struct httpd_fsdata_file_noconst *f;
复制代码

( F8 n' h/ D6 x( s1 O1 |

  M/ @3 D" h. _& I* Y- Uhttp-fsdata.c 中包含了所有页面的数据。这里的页面数据都转换为ACAll存在数组中,还包括了层叠样式表 (.css文件) 和图片。其数组结构如下:
. l: T% {0 \: i  [7 x
- R0 C: `7 w* [
  1. static const unsigned char data_404_html[] = {
    . k/ ^2 M! j7 r, V3 i' a
  2.     /* /404.html */+ j; h7 o- {* P) L6 e
  3.     0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,            //文件名  /404.html
    " ^5 V! S+ h/ A& i) N* k+ r
  4.      
    1 ^- Q9 v. O+ A
  5.     0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x20, 0x20, 0x3c,         //html文件转码为16进制数据(ASCLL)
    0 {+ N7 B  T# C( m! I' _+ b7 I5 d
  6.     0x62, 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f, 0x6c, 2 y, r3 ]; \0 U, m6 K- x3 j
  7.     0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65, 0x22,
    * [; F; X) }5 \0 G4 d
  8.     0x3e, 0xa, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x63, 0x65, 0x6e,
    - i4 @$ b: S) U; B2 d) d0 ?  H/ Y
  9.     0x74, 0x65, 0x72, 0x3e, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 1 F2 `3 x% c* `/ [5 H5 b* R/ V* V
  10.     0x20, 0x3c, 0x68, 0x31, 0x3e, 0x34, 0x30, 0x34, 0x20, 0x2d, ; r$ p- P: M2 C- b% Y/ I; w  Y. h/ C) J
  11.     0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, # z5 D$ y$ f. g  g6 b
  12.     0x66, 0x6f, 0x75, 0x6e, 0x64, 0x3c, 0x2f, 0x68, 0x31, 0x3e, % g5 {. s, k/ ^" Z! b
  13.     0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x68, 0x33, ) Y' {2 r  M; h# h' E5 T& I
  14.     0x3e, 0x47, 0x6f, 0x20, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65,
    * C0 a& t& ~3 [4 P0 z* |/ S
  15.     0x66, 0x3d, 0x22, 0x2f, 0x22, 0x3e, 0x68, 0x65, 0x72, 0x65,
    + L$ ~" Z' s, ]
  16.     0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x65,
    " N+ c# p0 z6 N$ K( W3 ?$ K" U
  17.     0x61, 0x64, 0x2e, 0x3c, 0x2f, 0x68, 0x33, 0x3e, 0xa, 0x20,
    ; k, k! \8 S0 ?4 S) k
  18.     0x20, 0x20, 0x20, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65,
    $ O: O! X; V$ H5 z8 g
  19.     0x72, 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x2f, 0x62, 0x6f, 0x64, % `" m3 P7 W" S. v8 T
  20.     0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e,
    - k+ M9 x% R$ |6 i& U1 q3 K# S
  21. 0};
复制代码
' |% t+ o# I7 N8 T4 N$ N  W; y) n& B
需要注意的是以下的一段程序:
  1. //结构体格式说明:      下一个页面地址(用于遍历网页)    ,网页name地址      ,html数据起始地址          ,html数据长度
    7 R8 W! v( F, S' ]3 H2 P
  2. //其中的加减操作是为了去除文件名的长度" n- k" v" H. R  `+ p. p- f- w2 K
  3. const struct httpd_fsdata_file file_processes_shtml[] = {{NULL, data_processes_shtml, data_processes_shtml + 17, sizeof(data_processes_shtml) - 17}};
    ' M! \( i  ~* o/ B
  4. 8 p1 x, F! [, M+ j" W3 Z; i
  5. const struct httpd_fsdata_file file_404_html[] = {{file_processes_shtml, data_404_html, data_404_html + 10, sizeof(data_404_html) - 10}};
    0 I4 ]3 r! Z$ y6 C( b

  6. * ]/ u! @" ?- b% h: w
  7. const struct httpd_fsdata_file file_files_shtml[] = {{file_404_html, data_files_shtml, data_files_shtml + 13, sizeof(data_files_shtml) - 13}};
    ; X. ^7 _/ ~8 b6 w0 `
  8. * `) I& v- m' l& J1 z
  9. const struct httpd_fsdata_file file_footer_html[] = {{file_files_shtml, data_footer_html, data_footer_html + 13, sizeof(data_footer_html) - 13}};' X1 s, Z8 i( W" Y

  10. 7 Q8 j/ E" w% p; I
  11. const struct httpd_fsdata_file file_header_html[] = {{file_footer_html, data_header_html, data_header_html + 13, sizeof(data_header_html) - 13}};& q  \- w  I) K8 L: c5 A9 A
  12. 4 O$ o+ }1 b4 ~) D( Q; u, F  ?  C% Q
  13. const struct httpd_fsdata_file file_index_html[] = {{file_header_html, data_index_html, data_index_html + 12, sizeof(data_index_html) - 12}};6 C2 Y4 ^, M/ O

  14. ; {# l, B- Y4 w3 _: x" C4 M9 O
  15. const struct httpd_fsdata_file file_style_css[] = {{file_index_html, data_style_css, data_style_css + 11, sizeof(data_style_css) - 11}};; J  v- a0 [* p, L5 o; T& i
  16. 1 U, Y. ]" [' V# F
  17. const struct httpd_fsdata_file file_tcp_shtml[] = {{file_style_css, data_tcp_shtml, data_tcp_shtml + 11, sizeof(data_tcp_shtml) - 11}};
    ; T* W  r  B& c6 t4 X$ S* Z1 B

  18. 5 U$ q+ _7 m. K9 v$ ?; [
  19. const struct httpd_fsdata_file file_fade_png[] = {{file_tcp_shtml, data_fade_png, data_fade_png + 10, sizeof(data_fade_png) - 10}};
    8 _2 z* h0 i; f7 s5 }( I: U: G
  20.   B3 \: s4 k; Z, y. F+ p8 e; N
  21. const struct httpd_fsdata_file file_stats_shtml[] = {{file_fade_png, data_stats_shtml, data_stats_shtml + 13, sizeof(data_stats_shtml) - 13}};/ b- F# [: J" }; u$ O# M7 h

  22. " v; Q" u4 ]. B/ E8 D; S
  23. #define HTTPD_FS_ROOT file_stats_shtml      //设定路由遍历入口页面,一定要保证所有页面都遍历过一次
    . ?$ d% e* l% n; q0 m
  24. % |' Z8 E, c* [
  25. #define HTTPD_FS_NUMFILES 10                //设定页面数量
复制代码
4 O0 `6 I9 f, M4 r! P4 r& {0 g
在 httpd_fs_open() 首先加载 file_stats_shtml页面数据 再加载file_stats_shtml结构体中下一个网页的数据 也就是file_fade_png的数据,同理 file_fade_png加载后一个页面数据  即 file_tcp_shtml数据 。。。 这样循环一次 就会加载所有的页面,实现里有遍历# Z2 e  n0 ~+ U5 e2 |( H) a
Uip WebServer的动态网页生成; u/ ~  ]5 i7 D/ e/ Q- G
在uip/apps/Webserver/http-fs/下有Webserver 页面未转码的html文件,其中有很多 %! 和 %!: 字符 :
3 n, D6 j& L5 W) w2 o6 x- S5 K
  1. %!: /header.html( [1 b0 j3 H: n& l
  2. <h1>Network statistics</h1>6 h/ u- O6 H6 |/ P3 D/ O5 @
  3. <center>7 ]+ F2 \" B# W7 v7 V
  4. <table width="300" border="0">2 V  p' E% t6 H
  5. <tr><td><pre>4 t/ d! Z) W9 ~( o1 ?
  6. IP           Packets received: l# g2 W% q: ?1 z) A
  7.              Packets sent, |! @9 z, S) `+ X% [
  8.          Packets dropped1 p9 C7 n" G" g! g; n0 ]0 G
  9. IP errors    IP version/header length0 ^$ |- Q7 \) M% c: e
  10.              IP length, high byte- M4 N; c; i+ ~  ]6 Z( P3 A
  11.              IP length, low byte" h' C) Z) F. p/ o
  12.              IP fragments0 e  N+ m7 V' H5 Q) S/ K  A; V& b' m
  13.              Header checksum" i& w' b* u7 z$ g9 [, c  k
  14.              Wrong protocol# Y% V- T8 S0 n$ X5 G6 F- `
  15. ICMP         Packets received
    5 j. o8 A9 D" X3 k% f& B; F/ B
  16.              Packets sent
    & M) [8 |7 q9 J: ]' W2 u: i
  17.              Packets dropped2 ]  v: Z  b8 v6 U! O0 a* R
  18.              Type errors! {) s' R) G  L, K2 F
  19. TCP          Packets received( L2 u# p" U/ _, t; Q
  20.              Packets sent# P7 I# t4 C2 d4 |6 K
  21.              Packets dropped4 _+ K# z% S/ q3 j2 n# O
  22.              Checksum errors+ q* Z9 o: l: H! `4 j1 f
  23.              Data packets without ACKs. b' v; V( N, O" W; `+ Q9 X
  24.              Resets
    7 O  }) a) W, X5 g/ n. z
  25.              Retransmissions
    - l8 e& g. G3 Y6 l& d( ?
  26.          No connection avaliable  q% ?- W. b* m6 s
  27.          Connection attempts to closed ports
    : Q: l1 u. u2 q  Y7 k. y% ]1 @
  28. </pre></td><td><pre>%! net-stats
    ' M, j0 x( b0 V- {
  29. </pre></table>% \( w$ [4 T# x+ m9 F8 [8 J% A# }
  30. </center>
    $ ]7 S& t6 W3 C" E5 P
  31. %!: /footer.html
复制代码
这是实现动态页面的关键。+ W6 ~; r' ]0 v: u( k% f/ q) v

1 Q" _$ `! n( c. X3 C- Qhandle_output()函数中,找到相应页面数据后,若页面为.shtml,则会调用handle_script()函数:
  1. static  PT_THREAD(handle_script(struct httpd_state *s))                             # \  e: M  g% f; G& F( h' C
  2. {' }0 `8 m9 n) Z! K# z
  3.   char *ptr;
    " ^2 N* e1 P. t3 [( A( e4 C/ L
  4.    , H& Z# H6 v  [4 ]
  5.   PT_BEGIN(&s->scriptpt);: D6 R6 W  A+ H6 Y) ~2 N
  6. 8 ]& d9 q; d% S8 c8 B1 E0 [
  7. 1 S: u+ u) e- @4 T# S5 N
  8.   while(s->file.len > 0) {
    . p( f) n4 o) K0 v3 r7 w( n

  9. 2 l5 N  \8 n5 {6 I! D8 f( Q  I
  10.     /* Check if we should start executing a script. */      //检测当前html数据(定义于httpd-fsdata.c)中是否存在字符 %! 和 %!:
    & ]; i% y5 ~. F
  11.     if(*s->file.data == ISO_percent &&
    1 V! t; ~/ q3 _# Q) L- P; ?5 V: E
  12.        *(s->file.data + 1) == ISO_bang) {                    , [8 S, A$ h4 I& `
  13.       s->scriptptr = s->file.data + 3;                        
    ' n1 H5 ^: V, k
  14.       s->scriptlen = s->file.len - 3;
    4 _# r- J, \* H( G' B8 k' A
  15.       if(*(s->scriptptr - 1) == ISO_colon) {             //若为 %!:  根据其后变量名,打开并输出相应文件
    & k, E4 S. z+ _) j: f; C: B
  16.     httpd_fs_open(s->scriptptr + 1, &s->file);                //eg.  %!: /header.html  打印/header.html* ^. F2 x' v: v3 J6 m2 k2 \# V
  17.     PT_WAIT_THREAD(&s->scriptpt, send_file(s));
    ) _$ O0 I& k0 K& M. P/ x" |
  18.       } else {                                  //若为 %!   根据其后变量名,调用相应处理程序(定义于httpd-cgi.c)
    : ]" q) X6 `1 r
  19.     PT_WAIT_THREAD(&s->scriptpt,                     //eg. %! file-stats     调用file-stats 绑定的file_stats()函数,打印出相关数据,实现动态网页
    + _$ H" `) e' A+ L
  20.                httpd_cgi(s->scriptptr)(s, s->scriptptr));" |1 l2 L, i& q4 \* x2 |0 b
  21.       }* X9 E$ V0 {4 s1 m( b
  22.       next_scriptstate(s);
    ' p0 b8 Z+ N( `* e) d" h- k
  23.       
    9 ~0 _  r9 v! R6 R  [% y
  24.       /* The script is over, so we reset the pointers and continue$ F, ~" Q& V# K# J0 s
  25.      sending the rest of the file. */" e$ k3 k9 k7 n( R) b
  26.       s->file.data = s->scriptptr;
    * q. r7 Q' n7 f% Z6 G0 |
  27.       s->file.len = s->scriptlen;
    & M( c# S& y5 }2 c$ H
  28.     } else {                                                //当前html数据不存在 %! 和 %!
    2 f* i2 v4 `4 R5 k
  29.       /* See if we find the start of script marker in the block of HTML5 R& i6 ^9 e/ ?: a
  30.      to be sent. */
    % m1 v3 `5 M' r, h: P

  31. . V. ?& ~0 P8 a3 E% W
  32.     ...略去
复制代码
5 O- p, U' }3 y7 v
uip 载入html数据的方法类似网页里的模板引擎的实现方法。当页面输出时,检测到有字符串 %! 和 %!: 时,则调用相应的cgi程序(httpd-cgi.c)处理,在httpd-cgi.c中做相应的数据处理,实现动态网页。
$ |8 k4 ~: L  w" O9 V

( A" `9 n, P5 v& e* W1 C, o- Y0 J& d% m
看一下效果吧
7 R! v5 p2 W2 X
9 t  H2 \; B' Y) D4 c
" m, L; ~8 x. }

web 访问

web 访问
赞 收藏 评论0 发布时间:2015-4-19 18:08

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版