目前共有14篇帖子。 内容转换:不转换▼
 
点击 回复
1054 13
【程序段】最简单的HTTP请求响应代码
一派护法 十九级
1楼 发表于:2017-3-18 17:09
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);
}
一派护法 十九级
2楼 发表于:2017-3-18 17:11
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信息去掉。
一派护法 十九级
3楼 发表于:2017-3-18 17:22
【变量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;
}
一派护法 十九级
4楼 发表于:2017-3-18 17:26
收到的HTTP响应:

一派护法 十九级
5楼 发表于:2017-3-18 17:35
【在网页上原封不动地显示浏览器请求内容】
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;
}
一派护法 十九级
6楼 发表于:2017-3-18 17:49
【在网页上原封不动地显示浏览器请求内容,且自动把\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;
}
一派护法 十九级
7楼 发表于:2017-3-18 17:52

自动换行的效果:

一派护法 十九级
8楼 发表于:2017-3-18 17:53
【测试用的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();
        }
    }
}
一派护法 十九级
9楼 发表于:2017-3-19 17:11
【智能化程序:自动计算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);
}
一派护法 十九级
10楼 发表于:2017-3-19 17:22
回复6楼 @巨大八爪鱼 的内容:
【在网页上原封不动地显示浏览器请求内容,且自动把\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;
}
一派护法 十九级
11楼 发表于:2017-3-19 17:32
【显示网页名称的程序】
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;
}
一派护法 十九级
12楼 发表于:2017-3-19 17:33
魔法学徒 一级
13楼 发表于:2017-4-7 11:05
大神 特来注册 感觉你对 lwip  很了解
一派护法 十九级
14楼 发表于:2017-4-7 21:58
回复13楼 @alsonjin 的内容:
大神 特来注册 感觉你对 lwip  很了解
请问你是?

回复帖子

内容:
用户名: 您目前是匿名发表
验证码:
(快捷键:Ctrl+Enter)
 

本帖信息

点击数:1054 回复数:13
评论数: ?
作者:巨大八爪鱼
最后回复:巨大八爪鱼
最后回复时间:2017-4-7 21:58
 
©2010-2024 Arslanbar Ver2.0
除非另有声明,本站采用知识共享署名-相同方式共享 3.0 Unported许可协议进行许可。