|   | 
      
                
        
           | 
          【程序段】最簡單的HTTP請求響應代碼 | 
         
                
          
            
                         一派掌門 二十級              | 
          
            
            
             
              err_t http_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) {     const char *str = "HTTP/1.1 200 OK\r\nDate: Sat, 13 Feb 2016 12:02:41 GMT\r\nServer: Apache/2.4.7 (Ubuntu)\r\nX-Powered-By: PHP/5.5.9-1ubuntu4.14\r\nContent-Length: 19\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: text/html\r\n\r\n<b>Hello World!</b>";     if (p != NULL)     {         tcp_write(tpcb, str, strlen(str), 0);         pbuf_free(p);     }     return ERR_OK; }
  err_t http_accept(void *arg, struct tcp_pcb *newpcb, err_t err) {     tcp_recv(newpcb, http_recv);     return ERR_OK; }
  void init_http(void) {     struct tcp_pcb *tpcb = tcp_new();     tcp_bind(tpcb, IP_ADDR_ANY, 80);     tpcb = tcp_listen(tpcb);     tcp_accept(tpcb, http_accept); }             
                       | 
         
                
          
            
                         一派掌門 二十級              | 
          
            
            
             
              const char *str = "HTTP/1.1 200 OK\r\nContent-Length: 19\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: text/html\r\n\r\n<b>Hello World!</b>"; 可以將響應字符串中的Date和Server信息去掉。              
             |  |
 
         
                
          
            
                         一派掌門 二十級              | 
          
            
            
             
              【變量i自加測試】 err_t http_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) {     static uint8_t i = 0;     char str[200];     sprintf(str, "HTTP/1.1 200 OK\r\nContent-Length: 12\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: text/html\r\n\r\n<b>i</b>=%-3d", i);     i++;          if (p != NULL)     {         tcp_write(tpcb, str, strlen(str), TCP_WRITE_FLAG_COPY); // str是局部變量, 函數退出時會被撤銷, 所以需要複製內存         pbuf_free(p);     }     return ERR_OK; }              
             |  |
 
         
                
          
            
                         一派掌門 二十級              | 
          
            
            
            
              收到的HTTP響應:               
             |  |
 
         
                
          
            
                         一派掌門 二十級              | 
          
            
            
             
              【在網頁上原封不動地顯示瀏覽器請求內容】 err_t http_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) {     char str[800];     uint16_t len;     if (p != NULL)     {         sprintf(str, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: text/html\r\n\r\n", p->len);         len = strlen(str);         strncpy(str + len, p->payload, p->len);         tcp_write(tpcb, str, len + p->len, TCP_WRITE_FLAG_COPY);         pbuf_free(p);     }     return ERR_OK; }              
             |  |
 
         
                
          
            
                         一派掌門 二十級              | 
          
            
            
             
              【在網頁上原封不動地顯示瀏覽器請求內容,且自動把\n換成<br>,方便查看】 err_t http_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) {     char ch;     char str[800];     uint16_t i, j, len;     if (p != NULL)     {         // 先統計一下HTML內容有多少         len = 0;         for (i = 0; i < p->len; i++) // 掃描整個請求字符串         {             ch = *((char *)p->payload + i);             if (ch == '\n')                 len += 4;             else if (ch != '\r') // 忽略\r字符                 len++;         }                  sprintf(str, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: text/html\r\n\r\n", len);         len = strlen(str); // 請求頭的長度         j = len;         for (i = 0; i < p->len; i++)         {             ch = *((char *)p->payload + i);             if (ch == '\n')             {                 // 換行符                 str[j++] = '<';                 str[j++] = 'b';                 str[j++] = 'r';                 str[j++] = '>';             }             else if (ch != '\r')                 str[j++] = ch; // 其他字符         }         tcp_write(tpcb, str, j, TCP_WRITE_FLAG_COPY);         pbuf_free(p);     }     return ERR_OK; }              
             |  |
 
         
                
          
            
                         一派掌門 二十級              | 
          
            
            
            
              自動換行的效果:
                
             |  |
 
         
                
          
            
                         一派掌門 二十級              | 
          
            
            
             
              【測試用的Java程序:用於查看返回的響應內容】 import java.io.IOException; import java.io.PrintWriter; import java.net.Socket; import java.net.UnknownHostException;
  public class Demo {     public static void main(String[] args) {         try {             Socket sock = new Socket("192.168.0.2", 80);             byte[] b = new byte[1024];                          PrintWriter pw = new PrintWriter(sock.getOutputStream());             pw.write("ha\r\nha");             pw.flush();                          sock.getInputStream().read(b);             System.out.println(new String(b));             sock.close();         } catch (UnknownHostException e) {             e.printStackTrace();         } catch (IOException e) {             e.printStackTrace();         }     } }              
             |  |
 
         
                
          
            
                         一派掌門 二十級              | 
          
            
            
             
              【智能化程序:自動計算HTML內容的長度】 #include <string.h> #include "lwip/tcp.h" // 一般情況下需要包含的頭文件
  #define STR_AND_SIZE(str) (str), strlen(str)
  err_t http_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) {     char len[10]; // 存放HTML內容的長度     char str[50]; // 存放HTML內容          const char *colors[] = {"red", "blue", "green"};     static int32_t i = 1;     static uint8_t color_i = 0;          if (p != NULL)     {         tcp_recved(tpcb, p->tot_len);                  // 動態生成HTML內容         sprintf(str, "<div><b style=\"color:%s\">i</b>=%d</div>", colors[color_i], i);         if (i == -1)             i = -2;         i = i * 2 + 1;         color_i++;         if (color_i == sizeof(colors) / sizeof(char *))             color_i = 0;                  sprintf(len, "%d", strlen(str)); // 計算出HTML內容的長度並轉換為字符串         tcp_write(tpcb, STR_AND_SIZE("HTTP/1.1 200 OK\r\nContent-Length: "), TCP_WRITE_FLAG_MORE);         tcp_write(tpcb, STR_AND_SIZE(len), TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);         tcp_write(tpcb, STR_AND_SIZE("\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: text/html\r\n\r\n"), TCP_WRITE_FLAG_MORE);         tcp_write(tpcb, STR_AND_SIZE(str), TCP_WRITE_FLAG_COPY); // 發送HTML內容         pbuf_free(p);     }     return ERR_OK; }
  err_t http_accept(void *arg, struct tcp_pcb *newpcb, err_t err) {     tcp_recv(newpcb, http_recv);     return ERR_OK; }
  void init_http(void) {     struct tcp_pcb *tpcb = tcp_new();     tcp_bind(tpcb, IP_ADDR_ANY, 80);     tpcb = tcp_listen(tpcb);     tcp_accept(tpcb, http_accept); }              
             |  |
 
         
                
          
            
                         一派掌門 二十級              | 
          
            
            
            
                            【在網頁上原封不動地顯示瀏覽器請求內容,且自動把\n換成<br>,方便查看】 err_t http_recv(void *arg, struct tcp_pcb *tpcb, str... 
			  【改進後的程序】 err_t http_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) {     char len[10]; // 存放HTML內容的長度     char str[500]; // 存放HTML內容     char ch;     uint16_t i;     uint16_t j = 0;     if (p != NULL)     {         for (i = 0; i < p->len; i++)         {             ch = *((char *)p->payload + i);             if (ch == '\n')             {                 // 換行符                 str[j++] = '<';                 str[j++] = 'b';                 str[j++] = 'r';                 str[j++] = '>';             }             else if (ch != '\r')                 str[j++] = ch; // 其他字符         }         tcp_recved(tpcb, p->tot_len);         sprintf(len, "%d", j); // j就是生成的HTML內容的長度                 tcp_write(tpcb, STR_AND_SIZE("HTTP/1.1 200 OK\r\nContent-Length: "), TCP_WRITE_FLAG_MORE);         tcp_write(tpcb, STR_AND_SIZE(len), TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);         tcp_write(tpcb, STR_AND_SIZE("\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: text/html\r\n\r\n"), TCP_WRITE_FLAG_MORE);         tcp_write(tpcb, str, j, TCP_WRITE_FLAG_COPY); // 發送HTML內容         pbuf_free(p);     }     return ERR_OK; }              
             |  |
 
         
                
          
            
                         一派掌門 二十級              | 
          
            
            
             
              【顯示網頁名稱的程序】 err_t http_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) {     char len[10]; // 存放HTML內容的長度     char str[200]; // 存放HTML內容          char name[100];     char *pstr;     uint8_t i = 0;     if (p != NULL)     {         // 提取頁面名稱         pstr = (char *)p->payload;         while (*pstr++ != ' ');         while (*pstr != ' ')             name[i++] = *pstr++;         name[i] = '\0'; // 不要忘了結束name字符串         tcp_recved(tpcb, p->tot_len);                  // 生成HTML內容         sprintf(str, "<meta charset=\"gb2312\"><title>獲取網頁名稱</title><div style=\"font-family:Arial\"><b>請求的網頁文件名稱是: </b>%s</div>", name);                  sprintf(len, "%d", strlen(str)); // HTML內容的長度         tcp_write(tpcb, STR_AND_SIZE("HTTP/1.1 200 OK\r\nContent-Length: "), TCP_WRITE_FLAG_MORE);         tcp_write(tpcb, STR_AND_SIZE(len), TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);         tcp_write(tpcb, STR_AND_SIZE("\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: text/html\r\n\r\n"), TCP_WRITE_FLAG_MORE);         tcp_write(tpcb, STR_AND_SIZE(str), TCP_WRITE_FLAG_COPY); // 發送HTML內容         pbuf_free(p);     }     return ERR_OK; }              
             |  |
 
         
                
          
            
                         一派掌門 二十級              | 
          
            
            
            
             |  |
 
         
                
          
            
                         魔法學徒 一級              | 
          
            
            
             
              大神 特來註冊 感覺你對 lwip  很了解             
             |  |
 
         
                
          
            
                         一派掌門 二十級              | 
          
            
            
            
             |  |
 
         
                 
                 | 
      
        
                       | 
        |