|
|
【程序段】最简单的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, s...
【改进后的程序】 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; }
|
一派护法 十九级 |
|
一派护法 十九级 |
|
|
|
|