CH9121与HTTP的结合(HTTP协议的解析,以及不同类型把请求的回复)

关于HTTP部分主要是解析http请求和响应,目前代码没发现问题,根据需要修改宏定义

前言:

HTTP协议(超文本传输协议HyperText Transfer Protocol),它是基于TCP协议的应用层传输协议,简单来说就是客户端和服务端进行数据传输的一种规则。

注意:客户端与服务器的角色不是固定的,一端充当客户端,也可能在某次请求中充当服务器。这取决与请求的发起端。HTTP协议属于应用层,建立在传输层协议TCP之上。客户端通过与服务器建立TCP连接,之后发送HTTP请求与接收HTTP响应都是通过访问Socket接口来调用TCP协议实现。

HTTP 是一种无状态 (stateless) 协议, HTTP协议本身不会对发送过的请求和相应的通信状态进行持久化处理。这样做的目的是为了保持HTTP协议的简单性,从而能够快速处理大量的事务, 提高效率。

然而,在许多应用场景中,我们需要保持用户登录的状态或记录用户购物车中的商品。由于HTTP是无状态协议,所以必须引入一些技术来记录管理状态,例如Cookie

正文

HTTP URL

HTTP URL 包含了用于查找某个资源的详细信息, 格式如下:

http://host[":"port][abs_path]

HTTP请求

http请求由请求行,消息报头,请求正文三部分构成。

HTTP请求状态行

请求行由请求MethodURL 字段和HTTP Version三部分构成, 总的来说请求行就是定义了本次请求的请求方式, 请求的地址, 以及所遵循的HTTP协议版本例如:

GET /example.html HTTP/1.1 (CRLF)

HTTP协议的方法有: GET: 请求获取Request-URI所标识的资源 POST: 在Request-URI所标识的资源后增加新的数据 HEAD: 请求获取由Request-URI所标识的资源的响应消息报头 PUT: 请求服务器存储或修改一个资源,并用Request-URI作为其标识 DELETE: 请求服务器删除Request-URI所标识的资源 TRACE: 请求服务器回送收到的请求信息,主要用于测试或诊断 CONNECT: 保留将来使用 OPTIONS: 请求查询服务器的性能,或者查询与资源相关的选项和需求

HTTP请求头

消息报头由一系列的键值对组成,允许客户端向服务器端发送一些附加信息或者客户端自身的信息

HTTP请求正文

只有在发送POST请求时才会有请求正文,GET方法并没有请求正文。

HTTP请求报文

HTTP响应

与HTTP请求类似HTTP响应也由三部分组成,包括状态行,消息报头,响应正文。

HTTP响应状态行

状态行也由三部分组成,包括HTTP协议的版本,状态码,以及对状态码的文本描述。例如:

HTTP/1.1 200 OK (CRLF)

HTTP响应状态码

状态代码有三位数字组成,第一个数字定义了响应的类别,且有五种可能取值: 1xx指示信息 - 表示请求已接收,继续处理 2xx成功 - 表示请求已被成功接收、理解、接受 3xx重定向 - 要完成请求必须进行更进一步的操作 4xx客户端错误 - 请求有语法错误或请求无法实现 * 5xx服务器端错误 - 服务器未能实现合法的请求

常见状态代码、状态描述、说明: 200: OK - 客户端请求成功 400: Bad Request - 客户端请求有语法错误,不能被服务器所理解 401: Unauthorized - 请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用 403: Forbidden - 服务器收到请求,但是拒绝提供服务 404: Not Found - 请求资源不存在,eg:输入了错误的URL 500: Internal Server Error - 服务器发生不可预期的错误 * 503: Server Unavailable - 服务器当前不能处理客户端的请求,一段时间后,可能恢复正常

HTTP响应状态码说明

HTTP响应报文

HTTP协议详解

HTTP的五大特点

  1. 支持客户/服务器模式。
  2. 简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GETHEADPOST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
  3. 灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
  4. 无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。早期这么做的原因是请求资源少,追求快。后来通过Connection: Keep-Alive实现长连接
  5. 无状态HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

正文:(创作不易,点个赞,点个收藏)

CH9121通信代码:

#include "CH9121.h"
#include "HTTP.h"
#include "API_1_1.h"

// 备注:两个读函数之间间隔510ms
// 定义接收和发送缓冲区,用动态申请大小

char net_rx_buf[512];

// 溢出标志
uint16_t overflow = 0;
uint8_t overflow_flag = 0;



void UART4_DMA_Init(void)
{
    // 初始化UART4和DMA1
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);	//使用外部中断或者重配置功能必须使能
    
    // 配置UART4的GPIO引脚
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 ;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOC, &GPIO_InitStructure);
    
    // 配置UART4
    USART_InitTypeDef USART_InitStructure;
    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(UART4, &USART_InitStructure);

        // 使能接收中断
    //USART_ITConfig(UART4, USART_IT_RXNE, ENABLE);
    
    USART_DMACmd(UART4, USART_DMAReq_Rx, ENABLE);
    
    DMA_InitTypeDef DMA_InitStructure;
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&UART4->DR;
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)net_rx_buf;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    DMA_InitStructure.DMA_BufferSize = 1024;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    
    DMA_Init(DMA1_Channel4, &DMA_InitStructure);
    

    DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE);
    DMA_Cmd(DMA1_Channel4, ENABLE);
    USART_Cmd(UART4, ENABLE);
    
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    // 启动UART4
    //
}


// 串口4初始化函数
void UART4_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    // 使能GPIO和USART时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);

    // 配置UART4的GPIO引脚
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; // TX
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; // RX
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    // 配置USART参数
    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    
    USART_ITConfig(UART4, USART_IT_RXNE, ENABLE);
    USART_ITConfig(UART4, USART_IT_IDLE, ENABLE);
    
    USART_Init(UART4, &USART_InitStructure);
    
    // 使能接收中断
    
    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    // 配置中断优先级
    NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    // 使能UART4
    USART_Cmd(UART4, ENABLE);
}



 /**
  * @brief  USART GPIO 配置,工作参数配置
  * @param  无
  * @retval 无
  */
void USART_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE);
	RCC_APB2PeriphClockCmd((RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD), ENABLE);
	
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOD, &GPIO_InitStructure);
	
	USART_InitStructure.USART_BaudRate = 115200;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No ;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_Init(UART5, &USART_InitStructure);

	USART_Cmd(UART5, ENABLE);	    
}


int fputc(int ch, FILE *f)
{
    USART_SendData(UART5, (uint8_t) ch);
    while (USART_GetFlagStatus(UART5, USART_FLAG_TXE) == RESET);
    return (ch);
}


// 模块串口参数初始化
Serial serial = 
{
    9600,
    None,
    0x08,
    0x01,
    0
};

// 模块客户端结构体成员初始化
Net_CommunitionType net_communition_Client = 
{
    2000,                   // 客户端端口号
    {192, 168, 5, 202},     // 客户端ip地址
    {255, 255, 255, 0},     // 客户端子网掩码
    {192, 168, 5, 202},     // 客户端默认网关
};

// 模块做服务器端结构体成员
Net_CommunitionType net_communition_Server1 = 
{
    2001,                   // 服务器端口号
    {192, 168, 4, 236},     // 服务器ip地址
    {255, 255, 255, 0},     // 服务器子网掩码
    {192, 168, 4, 1},       // 服雾器默认网关
};


// 如果模块用TCP client模式,这里的参数自行修改为目的服务器对应参数
Net_CommunitionType net_communition_DstServer = 
{
    1000,                   // 服务器端口号
    {192, 168, 5, 125},     // 服务器ip地址
    {255, 255, 255, 0},     // 服务器子网掩码
    {192, 168, 5, 1},       // 服雾器默认网关
};




static void Usartx_SendByte(USART_TypeDef * usart, uint8_t data)
{
    USART_SendData(usart, data);
    while (USART_GetFlagStatus(usart, USART_FLAG_TXE) == RESET);
    
}

static void Usartx_SendBytes(USART_TypeDef * usart, char * data, unsigned int len)
{
    for(int i = 0; i < len; i++){
        Usartx_SendByte(usart, data[i]);
    } 
}
uint8_t config_flag = 0;
// 进入配置模式
// 对于内部读写网口需要先调用此函数进入配置模式
static void ch9121_config_mode(void)
{
    config_flag = 1;
    // 发送命令字进入配置模式
    Usartx_SendByte(M_UARTX, 0x55);
    Usartx_SendByte(M_UARTX, 0xaa);
    Usartx_SendByte(M_UARTX, 0x5a);
    delay_ms(30);
    Usartx_SendByte(M_UARTX, 0XA5);
}

static void ch9121_exitconfige(void)
{
    // 发送命令字退出配置模式

    Usartx_SendByte(M_UARTX, EXIT_SERIAL_CONFIG);
    delay_ms(100);
    config_flag = 0;
}

// 更新配置参数到EEPROM
static void update_config(void)
{
    WRITE_CMD;
    Usartx_SendByte(M_UARTX, UPDATE_CONFIG);
}

// 执行配置
static void execution_config(void)
{
    WRITE_CMD;
    Usartx_SendByte(M_UARTX, CMD_EXECUTION);
}

// 配置为芯片为TCP Server模式
static void ch9121_TCP_Server(void)
{
    // 芯片进入配置模式
    ch9121_config_mode();
    delay_ms(100);
    // 配置为服务器模式
    WRITE_CMD;
    Usartx_SendByte(M_UARTX, SET_CHIP_MODE);
    Usartx_SendByte(M_UARTX, TCP_Server_mode);
    delay_ms(100);
    // 设置芯片IP地址 192.168.1.202
    WRITE_CMD;
    Usartx_SendByte(M_UARTX, SET_CHIP_IP);
    Usartx_SendByte(M_UARTX, net_communition_Server1.ip_address[0]);
    Usartx_SendByte(M_UARTX, net_communition_Server1.ip_address[1]);
    Usartx_SendByte(M_UARTX, net_communition_Server1.ip_address[2]);
    Usartx_SendByte(M_UARTX, net_communition_Server1.ip_address[3]);
    delay_ms(100);
    // 设置芯片子网掩码 255.255.255.0
    WRITE_CMD;
    Usartx_SendByte(M_UARTX, SET_CHIP_SUBNET_MASK);
    Usartx_SendByte(M_UARTX, net_communition_Server1.subnet_mask[0]);
    Usartx_SendByte(M_UARTX, net_communition_Server1.subnet_mask[1]);    
    Usartx_SendByte(M_UARTX, net_communition_Server1.subnet_mask[2]);
    Usartx_SendByte(M_UARTX, net_communition_Server1.subnet_mask[3]);  
    delay_ms(100);    
    // 设置芯片网关 192.168.1.1
    WRITE_CMD;
    Usartx_SendByte(M_UARTX, SET_CHIP_GATEWAY); 
    Usartx_SendByte(M_UARTX, net_communition_Server1.gateway[0]);
    Usartx_SendByte(M_UARTX, net_communition_Server1.gateway[1]);
    Usartx_SendByte(M_UARTX, net_communition_Server1.gateway[2]);
    Usartx_SendByte(M_UARTX, net_communition_Server1.gateway[3]);
    delay_ms(100);
    // 设置服务器端口2001,端口号发送字节序是先发低字节,再发高字节
    WRITE_CMD;
    Usartx_SendByte(M_UARTX, SET_LOCAL_PORT);  
    Usartx_SendByte(M_UARTX, net_communition_Server1.port_num & 0x0ff);
    Usartx_SendByte(M_UARTX, (uint8_t)(net_communition_Server1.port_num>>8));
    delay_ms(100);
    // 更新配置到EEPROM
    update_config();
    delay_ms(100);
    // 执行配置
    execution_config();
    delay_ms(100);
    // 退出配置模式
    ch9121_exitconfige();
}

// 配置为TCP Client模式
static void ch9121_TCP_Client(void)
{
    // 芯片进入配置模式
    ch9121_config_mode();
    delay_ms(100);
    // 配置为客户端模式
    WRITE_CMD;
    Usartx_SendByte(M_UARTX, SET_CHIP_MODE);
    Usartx_SendByte(M_UARTX, TCP_Client_mode);
    delay_ms(100);
/*
    //  已从上位机软件配置为DHCP模式,不需要配置IP、网关和子网掩码,端口号配置为了随机
    // 设置芯片IP地址 192.168.1.202   
    WRITE_CMD;
    Usartx_SendByte(M_UARTX, SET_CHIP_IP);
    Usartx_SendByte(M_UARTX, net_communition_Client.ip_address[0]);
    Usartx_SendByte(M_UARTX, net_communition_Client.ip_address[1]);
    Usartx_SendByte(M_UARTX, net_communition_Client.ip_address[2]);
    Usartx_SendByte(M_UARTX, net_communition_Client.ip_address[3]);
    // 设置芯片子网掩码 255.255.255.0
    WRITE_CMD;
    Usartx_SendByte(M_UARTX, SET_CHIP_SUBNET_MASK);
    Usartx_SendByte(M_UARTX, net_communition_Client.subnet_mask[0]);
    Usartx_SendByte(M_UARTX, net_communition_Client.subnet_mask[1]);    
    Usartx_SendByte(M_UARTX, net_communition_Client.subnet_mask[2]);
    Usartx_SendByte(M_UARTX, net_communition_Client.subnet_mask[2]);    
    // 设置芯片网关 192.168.1.1
    WRITE_CMD;
    Usartx_SendByte(M_UARTX, SET_CHIP_GATEWAY); 
    Usartx_SendByte(M_UARTX, net_communition_Client.gateway[0]);
    Usartx_SendByte(M_UARTX, net_communition_Client.gateway[1]);
    Usartx_SendByte(M_UARTX, net_communition_Client.gateway[2]);
    Usartx_SendByte(M_UARTX, net_communition_Client.gateway[3]);
    // 设置服务器端口2001,端口号发送字节序是先发低字节,再发高字节
    WRITE_CMD;
    Usartx_SendByte(M_UARTX, SET_LOCAL_PORT);  
    Usartx_SendByte(M_UARTX, net_communition_Client.port_num & 0x0ff);
    Usartx_SendByte(M_UARTX, (uint8_t)net_communition_Client.port_num>>8);
*/
    // 设置目的服务器IP地址
    WRITE_CMD;
    Usartx_SendByte(M_UARTX, SET_DESTINATION_IP);
    Usartx_SendByte(M_UARTX, net_communition_DstServer.ip_address[0]);
    Usartx_SendByte(M_UARTX, net_communition_DstServer.ip_address[1]);
    Usartx_SendByte(M_UARTX, net_communition_DstServer.ip_address[2]);
    Usartx_SendByte(M_UARTX, net_communition_DstServer.ip_address[3]);
    delay_ms(100);
    // 设置目的服务器端口1000,端口号发送字节序是先发低字节,再发高字节
    WRITE_CMD;
    Usartx_SendByte(M_UARTX, SET_DESTINATION_PORT);  
    Usartx_SendByte(M_UARTX, net_communition_DstServer.port_num & 0x0ff);
    Usartx_SendByte(M_UARTX, (uint8_t)(net_communition_DstServer.port_num>>8));   
    delay_ms(100);    
    // 更新配置到EEPROM
    update_config();
    delay_ms(100);
    // 执行配置
    execution_config();
    delay_ms(100);
    // 退出配置模式
    ch9121_exitconfige();
}




// 配置为UDP Client模式
static void ch9121_UDP(void)
{
    // 芯片进入配置模式
    ch9121_config_mode();
    delay_ms(100);
    // 配置为UDP客户端模式
    WRITE_CMD;
    Usartx_SendByte(M_UARTX, SET_CHIP_MODE);
    Usartx_SendByte(M_UARTX, UDP_Client_mode);
    delay_ms(100);
    // 设置目的服务器IP地址
    WRITE_CMD;
    Usartx_SendByte(M_UARTX, SET_DESTINATION_IP);
    Usartx_SendByte(M_UARTX, net_communition_DstServer.ip_address[0]);
    Usartx_SendByte(M_UARTX, net_communition_DstServer.ip_address[1]);
    Usartx_SendByte(M_UARTX, net_communition_DstServer.ip_address[2]);
    Usartx_SendByte(M_UARTX, net_communition_DstServer.ip_address[3]);
    delay_ms(100);
    // 设置目的服务器端口1000,端口号发送字节序是先发低字节,再发高字节
    WRITE_CMD;
    Usartx_SendByte(M_UARTX, SET_DESTINATION_PORT);  
    Usartx_SendByte(M_UARTX, net_communition_DstServer.port_num & 0x0ff);
    Usartx_SendByte(M_UARTX, (uint8_t)(net_communition_DstServer.port_num>>8)); 
    delay_ms(100);
    // 更新配置到EEPROM
    update_config();
    delay_ms(100);
    // 执行配置
    execution_config();
    delay_ms(100);
    // 退出配置模式
    ch9121_exitconfige();    
}

// 配置为UDP Server模式
static void ch9121_UDP_Server(void)
{
    // 芯片进入配置模式
    ch9121_config_mode();
    delay_ms(100);
    // 配置为UDP服务器端模式
    WRITE_CMD;
    Usartx_SendByte(M_UARTX, SET_CHIP_MODE);
    Usartx_SendByte(M_UARTX, UDP_Server_mode);
    delay_ms(100);
    // 设置目的服务器IP地址
    WRITE_CMD;
    Usartx_SendByte(M_UARTX, SET_DESTINATION_IP);
    Usartx_SendByte(M_UARTX, net_communition_DstServer.ip_address[0]);
    Usartx_SendByte(M_UARTX, net_communition_DstServer.ip_address[1]);
    Usartx_SendByte(M_UARTX, net_communition_DstServer.ip_address[2]);
    Usartx_SendByte(M_UARTX, net_communition_DstServer.ip_address[3]);
    delay_ms(100);
    // 设置目的服务器端口1000,端口号发送字节序是先发低字节,再发高字节
    WRITE_CMD;
    Usartx_SendByte(M_UARTX, SET_DESTINATION_PORT);  
    Usartx_SendByte(M_UARTX, net_communition_DstServer.port_num & 0x0ff);
    Usartx_SendByte(M_UARTX, (uint8_t)(net_communition_DstServer.port_num>>8)); 
    // 更新配置到EEPROM
    update_config();
    delay_ms(100);
    // 执行配置
    execution_config();   
    delay_ms(100);    
    // 退出配置模式
    ch9121_exitconfige();
}

// 选择ch9121的工作模式
// mode:0->TCP Server
//	 1->TCP Client
//       2->UDP
//       3->UDP Server
static void ch9121_mode_select(uint8_t mode)
{
	switch(mode)
	{
	case 0:
		ch9121_TCP_Server();
		break;
	case 1:
		ch9121_TCP_Client();
		break;
	case 2:
		ch9121_UDP();
		break;
	case 3:
		ch9121_UDP_Server();
		break;
	}
}




// 配置串口相关餐数
static void serial_config(void)
{
    // 芯片进入配置模式
    ch9121_config_mode();
    delay_ms(100);
    // 设置串口波特率926100,需要筹够4字节,发送字节序是先发低字节,再发高字节
    WRITE_CMD;
    Usartx_SendByte(M_UARTX, SET_SERIAL_BOUND);
    Usartx_SendByte(M_UARTX, serial.bound&0xff);
    Usartx_SendByte(M_UARTX, (serial.bound>>8)&0xff);
    Usartx_SendByte(M_UARTX, (serial.bound>>16)&0xff);
    Usartx_SendByte(M_UARTX, (serial.bound>>24)&0xff);
    delay_ms(100);
    // 设置串口数据帧格式,1位停止位,无校验,8位数据位
    WRITE_CMD;
    Usartx_SendByte(M_UARTX, SET_SERIAL_DATA_FORMAT);
    Usartx_SendByte(M_UARTX, serial.stop_bit);
    Usartx_SendByte(M_UARTX, serial.serial_check);
    Usartx_SendByte(M_UARTX, serial.data_bit);
    delay_ms(100);
    // 更新配置到EEPROM
    update_config();
    delay_ms(100);
    // 执行配置
    execution_config();
    delay_ms(100);
    // 退出配置模式
    ch9121_exitconfige();
}

// 发送数据
void send_netdata(uint8_t * t_buf)
{
    while(*t_buf != '\0')
    {
        Usartx_SendByte(M_UARTX, *t_buf);
        t_buf++;
    }
}


/*************************************************************************************************************************************************
                                                    读取相关函数
**************************************************************************************************************************************************/
// 读取芯片工作模式,返回一个字节
uint8_t read_WorkMode(void)
{
    uint8_t netmode;
    // 每次进来先把缓冲数组下标清零,便于取数
    overflow = 0;
    // 芯片进入配置模式
    //ch9121_config_mode();
    delay_ms(100);
    // 读取芯片工作模式,返回一个字节
    overflow = 0;
    WRITE_CMD;
    Usartx_SendByte(M_UARTX, READ_CHIP_MODE);
    delay_ms(100);
    // 退出配置模式
    //ch9121_exitconfige();
    
    netmode = net_rx_buf[0];
    printf("%d\r\n", netmode);
    switch(netmode)
    {
    case 0:
        return TCP_Server_mode;
    case 1:
        return TCP_Client_mode;
    case 2:
        return UDP_Server_mode;
    case 3:
        return UDP_Client_mode;
    }
    return 0xff;
}

// 读取芯片IP
void read_chip_ip(uint8_t *ip_addr)
{
    uint8_t i;
    // 每次进来先把缓冲数组下标清零,便于取数
    overflow = 0;
    // 芯片进入配置模式
    ch9121_config_mode();
    delay_ms(100);
    overflow = 0;
    // 读取芯片工作模式,返回一个字节
    WRITE_CMD;
    Usartx_SendByte(M_UARTX, READ_CHIP_IP);
    delay_ms(100);

    for(i = 0; i < 4; i++)
    {
        ip_addr[i] = net_rx_buf[i];
        
    }
    // 退出配置模式
    ch9121_exitconfige();
    printf("%d.%d.%d.%d\r\n", ip_addr[0],ip_addr[1],ip_addr[2],ip_addr[3]); 
}

// 读取芯片掩码
void read_chip_subnet_mask(uint8_t *subnet_mask)
{
    uint8_t i;
    // 每次进来先把缓冲数组下标清零,便于取数
    overflow = 0;
    // 芯片进入配置模式
    ch9121_config_mode();
    delay_ms(100);
    // 读取芯片工作模式,返回一个字节
    overflow = 0;
    WRITE_CMD;
    Usartx_SendByte(M_UARTX, READ_CHIP_SUBNET_MASK);
    delay_ms(300);
    for(i = 0; i < 4; i++)
    {
        subnet_mask[i] = net_rx_buf[i];
        
    }
    // 退出配置模式
    //ch9121_exitconfige();
    printf("%d.%d.%d.%d\r\n", subnet_mask[0],subnet_mask[1],subnet_mask[2],subnet_mask[3]); 
}


// 读取芯片掩码
void read_chip_getway(uint8_t *getway)
{
    uint8_t i;
    // 每次进来先把缓冲数组下标清零,便于取数
    overflow = 0;
    // 芯片进入配置模式
    ch9121_config_mode();
    delay_ms(100);
    // 读取芯片工作模式,返回一个字节
    overflow = 0;
    WRITE_CMD;
    Usartx_SendByte(M_UARTX, READ_CHIP_GATEWAY);
    delay_ms(300);
    for(i = 0; i < 4; i++)
    {
        getway[i] = net_rx_buf[i];
        
    }
    // 退出配置模式
    //ch9121_exitconfige();
    printf("%d.%d.%d.%d\r\n", getway[0],getway[1],getway[2],getway[3]); 
}

// 读取源端口
uint16_t read_source_port(void)
{
    uint16_t _port;
    // 每次进来先把缓冲数组下标清零,便于取数
    overflow = 0;
    // 芯片进入配置模式
    //ch9121_config_mode();
    delay_ms(100);
    overflow = 0;
    // 读取芯片工作模式,返回一个字节
    WRITE_CMD;
    
    Usartx_SendByte(M_UARTX, READ_SOURCE_PORT);
    delay_ms(300);   
    // 退出配置模式
    //ch9121_exitconfige();
    
    _port = net_rx_buf[0];
    _port |= (net_rx_buf[1]<<8);  
    printf("%d\r\n", _port);
    return _port;
}
    
// 读取目的IP
void read_distination_ip(uint8_t *ip_addr)
{
    uint8_t i;
    // 每次进来先把缓冲数组下标清零,便于取数
    overflow = 0;
    // 芯片进入配置模式
    //ch9121_config_mode();
    delay_ms(300);
    // 读取芯片工作模式,返回一个字节
    WRITE_CMD;
    Usartx_SendByte(M_UARTX, READ_DESTINATION_IP);
    delay_ms(300);
    for(i = 0; i < 4; i++)
    {
        ip_addr[i] = net_rx_buf[i];
        
    }
    // 退出配置模式
    //ch9121_exitconfige();
    printf("%d.%d.%d.%d\r\n", ip_addr[0],ip_addr[1],ip_addr[2],ip_addr[3]); 
}

// 读取目的端口
uint16_t read_distination_port(void)
{
    uint16_t _port;
    // 每次进来先把缓冲数组下标清零,便于取数
    overflow = 0;
    // 芯片进入配置模式
    //ch9121_config_mode();
    delay_ms(300);
    // 读取芯片工作模式,返回一个字节
    WRITE_CMD;
    Usartx_SendByte(M_UARTX, READ_DESTINATION_PORT);
    delay_ms(300);   
    // 退出配置模式
    //ch9121_exitconfige();
    
    _port = net_rx_buf[2];
    _port |= (net_rx_buf[3]<<8);  
    printf("%d\r\n", _port);
    return _port;
}

// 复位芯片
void reset_chip(void)
{
    // 芯片进入配置模式
    ch9121_config_mode();
    delay_ms(300);
    WRITE_CMD;
    Usartx_SendByte(M_UARTX, RESET_CHIP);
    delay_ms(300);
    // 退出配置模式
    ch9121_exitconfige();
}

// 初始化配置函数
void init_ch9121(void)
{
    // 设置工作模式
    config_flag = 1;
    //ch9121_mode_select(TCP_Server_mode);
    read_chip_getway(net_communition_Server1.gateway);
    read_chip_subnet_mask(net_communition_Server1.subnet_mask);
    read_chip_ip(net_communition_Server1.ip_address);
    net_communition_Server1.port_num = read_source_port();
    config_flag = 0;
}




uint8_t RecvFlag  = 0;
/**
 * @name	  UART4_IRQHandler
 * @brief     串口4中断服务函数,目前用于CH9121网络通信模块
 * @param	  空
 * @return    空
 * @DateTime  2019-7-20
 */
uint8_t return_val = 0;
void UART4_IRQHandler(void)
{
    if(USART_GetITStatus(UART4, USART_IT_RXNE) != RESET)
    {		
        return_val = USART_ReceiveData(UART4);
        if(overflow > 2047)
        {
            overflow = 0;
        }
        else 
        {
            net_rx_buf[overflow++] = return_val;
        }
     } 
     else if(USART_GetITStatus(UART4, USART_IT_IDLE) != RESET)
     {
         USART_ReceiveData(M_UARTX);
         
         RecvFlag = 1;
     }
}

CH9121.h

// 定义了与网络CH9121通信的基本数据结构,和配置结构,参数等
#ifndef __BSP_CH9121_H__
#define __BSP_CH9121_H__


#include "Global.h"
#include <stdio.h>
// 本程序中默认模块做为客户端
#define M_UARTX				UART4

#define WRITE_CMD           {Usartx_SendByte(M_UARTX, 0x57);Usartx_SendByte(M_UARTX, 0xab);}
#define delay_ms(X) os_dly_wait(X)

// 定义接收和发送缓冲区,用动态申请大小,打包长度小于1024byte

extern char net_rx_buf[512];
extern uint8_t overflow_flag;
// 网络连接状态类型
typedef enum _ConnectStatus
{
	disconnect = 0,
	connect_ok
} ConnectStatus;

// 校验方式数据类型
typedef enum _Serial_Check
{
	Even_Check = 0,
	Odd_Check,
	Mark,
	Space,
	None
} Serial_Check;

// 工作模式类型
typedef enum _Net_Mode
{
	TCP_Server_mode = 0,
	TCP_Client_mode,
	UDP_Server_mode,
	UDP_Client_mode
} Net_Mode;

// 服务器/客户端通信相关的类型
typedef struct _Net_CommunitionType
{
	uint16_t port_num;			// 端口号
	uint8_t ip_address[4];			// IP地址
	uint8_t subnet_mask[4];			// 子网掩码
	uint8_t gateway[4];			// 默认网关
    uint16_t tcp_retry_count;		// TCP重试次数
	uint8_t mac_address[4];			// MAC地址
	ConnectStatus status;			// 连接状态
    Net_Mode net_mode;
} Net_CommunitionType;
extern Net_CommunitionType net_communition_Client;
extern Net_CommunitionType net_communition_DstServer;
extern Net_CommunitionType net_communition_Server1;

// 串口相关数据类型
typedef struct _Serial
{
	uint32_t bound;		    // 波特率
	Serial_Check serial_check;  // 校验类型
	uint8_t data_bit;	    // 数据位数
	uint8_t stop_bit;	    // 停止位
	uint32_t timeout;	    // 超时时间
} Serial;

typedef struct{
    unsigned char year;
    unsigned char mon;
    unsigned char mday;
    unsigned char wday;
    unsigned char hour;
    unsigned char min;
    unsigned char sec;
}tm_time;

typedef struct {
    unsigned int batchNumber;
    tm_time pointDate;
    int temperatrue;
    int speed;
    int ascspeed;
    int descspeed;
}tm_msg;



typedef struct {
    unsigned int batchNumber;
    int state;
    char reason[30];
}tm_state;

typedef struct {
    char success;
    char title;
    char message;
    char type;
    char detail[30];
    char category;
}boby_result;

extern Serial serial;


// 写命令码,格式(0x57 0xab + 命令码 + 数据)
#define RESET_CHIP			0x02		// 复位命令,芯片重新运行 
#define UPDATE_CONFIG			0x0d		// 更新配置参数至 EEPROM 
#define CMD_EXECUTION			0x0e		// 命令执行
#define SET_CHIP_MODE			0x10		// 设置模式
#define SET_CHIP_IP			0x11		// 设置芯片 IP 地址
#define SET_CHIP_SUBNET_MASK	        0x12		// 设置芯片掩码 
#define SET_CHIP_GATEWAY		0x13		// 设置芯片网关 
#define SET_LOCAL_PORT			0x14		// 设置芯片本地端口 
#define SET_DESTINATION_IP		0x15		// 设置芯片目的 IP 地址
#define SET_DESTINATION_PORT	        0x16		// 设置芯片目的端口
#define SET_SERIAL_BOUND		0x21		// 设置串口波特率 
#define SET_SERIAL_DATA_FORMAT	        0x22		// 设置串口校验位数据位停止位
#define EXIT_SERIAL_CONFIG		0x5e		// 退出串口配置模式

// 读命令码,格式(0x57 0xab + 命令码)
#define READ_CHIP_MODE			0x60		// 读取芯片工作模式,返回 1 字节 
#define READ_CHIP_IP			0x61		// 读取芯片 IP 地址,返回 4 字节 
#define READ_CHIP_SUBNET_MASK	        0x62		// 读取芯片掩码,返回 4 字节 
#define READ_CHIP_GATEWAY		0X63		// 读取芯片网关,返回 4 字节 
#define READ_SOURCE_PORT	        0x64		// 读取芯片源端口号,返回 2 字节
#define READ_DESTINATION_IP 	        0x65		// 读取芯片目的 IP 地址,返回 4 字节
#define READ_DESTINATION_PORT	        0x66		// 读取芯片目的端口号,返回 2 字节 
#define READ_RETRY_TIMES		0x67		// 读取 TCP 重试次数,返回 1 字节 
#define READ_SERIAL_BOUND		0x71		// 读取串口波特率,返回 4 字节 
#define READ_SERIAL_DATA_FORMAT         0x72		// 读取串口校验位数据位停止位,返回 3 字节
#define READ_SERIAL_OVERTIME	        0x73		// 读取串口超时时间,返回 1 字节 
#define READ_MAC_ADDRESS		0x81		// 读取 MAC 地址,返回 6 字节 
#define READ_TCP_STATUS			0x03		// 读取 TCP 连接状态(TCP CLIENT 模式下),返回 1 字节,1:连接,0:断开。 










extern tm_time system_tm;
extern uint8_t ConfigFlag;

// 公有函数区域
    void UART4_Init(void);
void init_ch9121(void);
void send_netdata(uint8_t * t_buf);
uint8_t read_WorkMode(void);
uint16_t read_source_port(void);
void read_chip_ip(uint8_t *ip_addr);
uint16_t read_distination_port(void);
void read_distination_ip(uint8_t *ip_addr);
void reset_chip(void);
__task void CH9121_Token_Get(void);
__task void CH9121_HTTP_CL(void);
#endif	

HTTP.c

#include "HTTP.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>

/*
	状态码	状态消息	描述
	1xx	信息性状态码	表示服务器已经接收到请求,并且正在处理请求
	100	Continue	客户端应该继续发送请求
	101	Switching Protocols	服务器正在切换协议
	2xx	成功状态码	表示服务器成功地接收、理解并接受请求
	200	OK	请求已经成功处理并返回响应
	201	Created	请求已经成功处理并创建了新资源
	202	Accepted	请求已经接受,但是还没有处理
	204	No Content	请求已经成功处理,但是没有响应内容
	
	3xx	重定向状态码	表示请求需要进一步处理才能完成
	301	Moved Permanently	请求的资源已经被永久移动到新的URL
	302	Found	请求的资源已经被暂时移动到新的URL
	304	Not Modified	请求的资源没有被修改,可以使用缓存副本
	
	4xx	客户端错误状态码	表示客户端发出的请求有问题,服务器无法处理
	400	Bad Request	请求无效或无法处理
	401	Unauthorized	需要认证才能访问资源
	403	Forbidden	没有访问资源的权限
	404	Not Found	请求的资源不存在
	
	5xx	服务器错误状态码	表示服务器在处理请求时遇到了问题
	500	Internal Server Error	服务器遇到了无法处理的错误
	502	Bad Gateway	充当网关或代理服务器的服务器从上游服务器接收到的响应无效
	503	Service Unavailable	服务器无法处理请求,可能是因为过载或正在维护
*/
static const char *http_codes[53] = {
    "100 Continue",
    "101 Switching Protocols",
    "102 Processing",
    "200 OK",
    "201 Created",
    "202 Accepted",
    "203 Non-Authoritative Information",
    "204 No Content",
    "205 Reset Content",
    "206 Partial Content",
    "207 Multi-Status",
    "208 Already Reported",
    "226 IM Used",
    "300 Multiple Choices",
    "301 Moved Permanently",
    "302 Found",
    "303 See Other",
    "304 Not Modified",
    "305 Use Proxy",
    "307 Temporary Redirect",
    "308 Permanent Redirect",
    "400 Bad Request",
    "401 Unauthorized",
    "402 Payment Required",
    "403 Forbidden",
    "404 Not Found",
    "405 Method Not Allowed",
    "406 Not Acceptable",
    "407 Proxy Authentication Required",
    "408 Request Timeout",
    "409 Conflict",
    "410 Gone",
    "411 Length Required",
    "412 Precondition Failed",
    "413 Payload Too Large",
    "414 URI Too Long",
    "415 Unsupported Media Type",
    "416 Range Not Satisfiable",
    "417 Expectation Failed",
    "418 I'm a teapot",
    "421 Misdirected Request",
    "422 Unprocessable Entity",
    "423 Locked",
    "424 Failed Dependency",
    "426 Upgrade Required",
    "428 Precondition Required",
    "429 Too Many Requests",
    "431 Request Header Fields Too Large",
    "451 Unavailable For Legal Reasons",
    "500 Internal Server Error",
    "501 Not Implemented",
    "502 Bad Gateway",
    "503 Service Un"
};
// 获取指定状态码的状态消息
const char* get_http_status_message(int status_code) {
    static const char unknown[] = "Unknown status code";
    char *description = NULL;
    char num_ch[30];
    int i;
    snprintf(num_ch, 30, "%d", status_code);
    for (i = 0; i < 53; i++) {
        if(strncmp(http_codes[i], num_ch, 3) == 0){
            return http_codes[i];
        }
    }
    return unknown;
}





/**
  * @brief  StringBF 
  * @param  s1:源字符串 
			s2:子串 
			pos:开始查找位置
			这个函数和C库函数一样的用法,但是原来的C库函数有问题,所以优化了写法 
  * @retval result:查找字符串出现的位置
  */
char *Strtok(char *s1, const char *s2)
{
    int i = 0;//下标值与自然语言转换 
    int j = 0;
    int m = 0;
    static char* saved_ptr = NULL;
	
    // 如果是第一次调用,则初始化 saved_ptr
    if (s1 != NULL) {
        saved_ptr = s1;
    } else if (saved_ptr == NULL) {
        // 如果 saved_ptr 为 NULL,则返回 NULL
        return NULL;
    }
    
    char * token = saved_ptr;
    int s2_len = strlen(s2), s1_len = strlen(saved_ptr);
    
    while(i < s1_len && j < s2_len)//若i和j都大于字符串的长度就结束循环
    {
        if(saved_ptr[i] == s2[j])                   
        {
            i++;
            j++;
        }
        else//匹配失败时回溯 
        {
            i = i - j + 1;	//被匹配字符串右移1 
            j = 0;			//匹配字符串初始化下标值 
        }
        
    }
    if(j == s2_len)//联合上面的while进行对比
	{
		for(m =  0; m < s2_len; m++){
			saved_ptr[i - m -1] = 0;
		}
		
		saved_ptr = saved_ptr + i;
		return token;	
	}
	else saved_ptr = NULL;
	
	return token;
     //返回的是第一次匹配到的字符的下自然语言(则从1开始数)
}

http_url_t* parse_http_from(http_url_t * urlt, char *query_string) {
    int i = 0, j = 0;
    char * pair[MAX_HTTP_URI_FROM_COUNT];
    char *query = Strtok((char *)query_string, "?");
    strncpy(urlt->path, query, MAX_HTTP_URI_PATH_LEN);
    urlt->path[MAX_HTTP_URI_PATH_LEN - 1] = '\0';
     
    while(i < MAX_HTTP_URI_FROM_COUNT && pair[i]){
    	pair[i] = Strtok((char *)NULL, "&");
    	
    	if(pair[i] == NULL) break;
    	i++;
	}
    
    while (pair[j] && j < i) {
        char *key = Strtok(pair[j], "=");
        char *value = Strtok(NULL, "=");
        if(key == NULL || value == NULL){
        	return NULL;
		}
        strncpy(urlt->urlf[j].key, key, MAX_HTTP_URI_FROM_LEN);
        urlt->urlf[j].key[MAX_HTTP_URI_FROM_LEN - 1] = '\0';
        
        strncpy(urlt->urlf[j].value, value, MAX_HTTP_URI_FROM_LEN);
        urlt->urlf[j].value[MAX_HTTP_URI_FROM_LEN - 1] = '\0';
        j++;
        
    }
    urlt->count = i;
    return urlt;
}


http_request_t *parse_http_request(http_request_t *request, char * request_string) {
    //http_request_t *request = (http_request_t *)malloc(sizeof(http_request_t));
    
		
    if (!request) {
        return NULL;
    }
	
	char *request_line_str = Strtok(request_string, "\r\n");
    char *header_str = Strtok(NULL, "\r\n\r\n");
    char *body_str = Strtok(NULL, "\r\n");
    
    if(body_str != NULL){
    	strncpy(request->body, body_str, MAX_HTTP_BODY_LEN);
    	request->body[MAX_HTTP_BODY_LEN - 1] = '\0';
	}
    
    
    if (!request_line_str) {
        free(request);
        return NULL;
    }

	//解析请求行 
    char *request_line_tokens[3];
    int num_request_line_tokens = 0;
    char *token = Strtok(request_line_str, " ");
    
    while (token != NULL && num_request_line_tokens < 3) {
        request_line_tokens[num_request_line_tokens++] = token;
        token = Strtok(NULL, " ");
    }
    
    if (num_request_line_tokens < 3) {
        free(request);
        return NULL;
    }
    
    strncpy(request->request_line.method, request_line_tokens[0], MAX_HTTP_METHOD_LEN);
    request->request_line.method[MAX_HTTP_METHOD_LEN - 1] = '\0';

	http_url_t * urls = parse_http_from(&(request->request_line.uri), request_line_tokens[1]);
    
	strncpy(request->request_line.version, request_line_tokens[2], MAX_HTTP_VERSION_LEN);
    request->request_line.version[MAX_HTTP_VERSION_LEN - 1] = '\0';



    char * header_key,* header_value;
    header_key = Strtok(header_str, ": ");
    
    //解析请求头 
    while (header_key != NULL && request->head_count < MAX_HTTP_HEADER_COUNT) {
  		
        header_value = Strtok(NULL, "\r\n");

        http_header_t *header = &(request->headers[request->head_count++]);
        
        strncpy(header->key, header_key, MAX_HTTP_HEADER_LEN);
        header->key[MAX_HTTP_HEADER_LEN - 1] = '\0';

        strncpy(header->value, header_value, MAX_HTTP_HEADER_LEN);
        header->value[MAX_HTTP_HEADER_LEN - 1] = '\0';
        
        header_key = Strtok(NULL, ": ");
    }
    
    if (request->head_count == 0) {
        free(request);
        return NULL;
    }
	
    return request;
}


char * http_request_respond(char * http_version, char * content_type, int  state_code, char * body, int content_length){
    static char rec[2048];
    memset(rec, 0, 2048);
    snprintf(rec, 2048, HTTP_RESPOND, http_version, get_http_status_message(state_code), content_type, content_length, body);
    return rec;
}


void printf_http_request(http_request_t * request){
	printf("method:%s\n", request->request_line.method);
	printf("version:%s\n", request->request_line.version);
	printf("path:%s\n", request->request_line.uri.path);
	for(int i = 0; i < request->request_line.uri.count; i++){
		printf("%s:%s\n", request->request_line.uri.urlf[i].key, request->request_line.uri.urlf[i].value);
	}
	printf("header:{\n");	
	for(int i = 0; i < request->head_count; i++){
		printf("\t%s:%s\n", request->headers[i].key, request->headers[i].value);
	}
	printf("}\n");	
	printf("body:%s\n", request->body);	
}




char get_request_string[] = "POST /cmds?device_id=1005271920&qos=1&timeout=10 HTTP/1.1\r\nHost:api.heclouds.com\r\nConnection: keep-alive\r\nContent-Type:application/x-www-form-urlencoded\r\nContent-Length:16\r\napi-key:uCmAn8tHKuuqJe5KllaobZiN=Og=\r\n\r\nhhhhhhhhhhhhhhhh\r\n";

static uint32_t mt[MT_N];
static int mti = MT_N + 1;

void mt_seed(uint32_t seed) {
    mt[0] = seed;
    for (mti = 1; mti < MT_N; mti++) {
        mt[mti] = 1812433253 * (mt[mti - 1] ^ (mt[mti - 1] >> 30)) + mti;
    }
}

uint32_t mt_rand() {
    uint32_t y;


    if (mti >= MT_N) {
        int i;
        for (i = 0; i < MT_N - MT_M; i++) {
            y = (mt[i] & MT_UPPER_MASK) | (mt[i + 1] & MT_LOWER_MASK);
            mt[i] = mt[i + MT_M] ^ (y >> 1) ^ ((y & 1) * MT_MATRIX_A);
        }
        for (; i < MT_N - 1; i++) {
            y = (mt[i] & MT_UPPER_MASK) | (mt[i + 1] & MT_LOWER_MASK);
            mt[i] = mt[i + (MT_M - MT_N)] ^ (y >> 1) ^ ((y & 1) * MT_MATRIX_A);
        }
        y = (mt[MT_N - 1] & MT_UPPER_MASK) | (mt[0] & MT_LOWER_MASK);
        mt[MT_N - 1] = mt[MT_M - 1] ^ (y >> 1) ^ ((y & 1) * MT_MATRIX_A);
        mti = 0;
    }

    y = mt[mti++];
    y ^= y >> 11;
    y ^= (y << 7) & 0x9D2C5680;
    y ^= (y << 15) & 0xEFC60000;
    y ^= y >> 18;

    return y;
}


char *generate_token(int seed) {
    const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; // 定义Token可以使用的字符集
    static char token[TOKEN_LENGTH+2];
    mt_seed(seed); // 设置随机数生成器的种子

    for (int i = 0; i < TOKEN_LENGTH; i++) {
        int index = mt_rand() % (sizeof(charset) - 1); // 从字符集中随机选择一个字符
        token[i] = charset[index];
    }

    token[TOKEN_LENGTH] = '\0'; // 在Token的末尾添加字符串结束符
    printf("token:%s\n", token);
    return token;
}



HTTP.h

#ifndef __HTTP_H
#define __HTTP_H

#define MAX_HTTP_METHOD_LEN 10
#define MAX_HTTP_URI_LEN 100
#define MAX_HTTP_URI_FROM_COUNT 10
#define MAX_HTTP_URI_PATH_LEN 100
#define MAX_HTTP_HOST_LEN 30
#define MAX_HTTP_URI_FROM_LEN 100
#define MAX_HTTP_VERSION_LEN 20
#define MAX_HTTP_HEADER_LEN 200
#define MAX_HTTP_BODY_LEN 400
#define MAX_HTTP_HEADER_COUNT 10
#define MAX_HTTP_RESPOND_LEN 500
/**

    *HTTP请求行包含三个部分:
    *请求方法(Request Method):指明了客户端想要执行的动作。常见的请求方法有GET、POST、PUT、DELETE等。例如,GET方法表示客户端希望从服务器获取资源。
    *请求URI(Request URI):指定了要访问的资源的标识符。URI通常包括协议、主机名、端口号和路径等信息。例如,http://www.example.com/index.html是一个请求URI。
    *HTTP协议版本(HTTP Version):指定了客户端所使用的HTTP协议的版本。常见的HTTP协议版本有HTTP/1.0和HTTP/1.1等。例如,HTTP/1.1表示客户端正在使用HTTP协议的1.1版本。
    *例如,以下是一个HTTP请求行的例子:
    *GET /index.html HTTP/1.1
    *   其中,GET是请求方法,/index.html是请求URI,HTTP/1.1是HTTP协议版本。
 **/

/**
  *  text/html:HTML文本文档类型,用于表示HTML网页。
  *  application/json:JSON数据类型,用于表示结构化数据。
  *  application/xml:XML数据类型,用于表示结构化数据。
  *  image/jpeg:JPEG图像类型,用于表示JPEG格式的图像。
  *  image/png:PNG图像类型,用于表示PNG格式的图像。
  *  text/plain:纯文本类型,用于表示文本文件。
  *  application/pdf:PDF文档类型,用于表示PDF文件。
  *  application/javascript:JavaScript文件类型,用于表示JavaScript代码文件。
  *  application/octet-stream:二进制流类型,用于表示二进制文件,如图片、视频等。
**/
#define HTTP_RESPOND "%s %s\r\nContent-Type: %s\r\nContent-Length: %d\r\n\r\n%s"

#define HTTP_VERSION "HTTP/1.1"
#define CONTENT_TYPE "application/json"     //"application/x-www-form-urlencoded; charset=UTF-8"
#define HTTP_GET "GET"
#define HTTP_POST "POST"
#define HTTP_404 "<!DOCTYPE html><html><head><title>404 Not Found</title></head><body><h1>404 Not Found</h1><p>The page you requested could not be found.</p></body></html>"


#define TOKEN_LENGTH 32 // 定义Token的长度
#define MT_N 624
#define MT_M 397
#define MT_MATRIX_A 0x9908B0DF
#define MT_UPPER_MASK 0x80000000
#define MT_LOWER_MASK 0x7FFFFFFF


typedef struct {
    char key[MAX_HTTP_URI_FROM_LEN];
    char value[MAX_HTTP_URI_FROM_LEN];
} http_url_form;

typedef struct {
	int count;
	char path[MAX_HTTP_URI_PATH_LEN];
    http_url_form urlf[MAX_HTTP_URI_FROM_COUNT];
} http_url_t; 
 
typedef struct {
	http_url_t uri;       //请求URL
    char method[MAX_HTTP_METHOD_LEN]; //请求方法
    char version[MAX_HTTP_VERSION_LEN];
} http_request_line_t;

//请求头 
typedef struct {
    char key[MAX_HTTP_HEADER_LEN];
    char value[MAX_HTTP_HEADER_LEN];
} http_header_t;

typedef struct {
    http_request_line_t request_line;
    int head_count;
    http_header_t headers[MAX_HTTP_HEADER_COUNT];
    char body[MAX_HTTP_BODY_LEN];
} http_request_t;

typedef struct {
    char version[MAX_HTTP_VERSION_LEN];
    int status_code;
    int head_count;
    char content_type[MAX_HTTP_HEADER_LEN];
    http_header_t headers[MAX_HTTP_HEADER_COUNT];
    char body[MAX_HTTP_RESPOND_LEN];
} http_respond_t;


char *generate_token(int seed);
void printf_http_request(http_request_t * request);
//http_request_t *parse_http_request(char *request_string);
http_request_t *parse_http_request(http_request_t *request, char *request_string); 
http_url_t* parse_http_from(http_url_t * urlt, char *query_string);
const char* get_http_status_message(int status_code);
char * http_request_respond(char * http_version, char * content_type, int  state_code, char * body, int content_length);







#endif









示例:

__task void CH9121_HTTP_CL(void)
{
    char * tx_data;
    
    reset_chip();
    os_dly_wait(3000);
    ConfigFlag = 0;
    
    
    init_ch9121();
    int login = 0;
    

    overflow = 0;
    RecvFlag = 0;
    ConfigFlag = 1;
    
    uint32_t old_speed = 0;
    
    while(1)
    {   
        if(ConfigFlag == 1)
        {
            
            // 设置工作模式
            overflow = 0;
            ch9121_mode_select(TCP_Server_mode);
            ConfigFlag = 0;
            RecvFlag = 0;
            overflow = 0;
        }
        if(ConfigFlag == 2)
        {
            
            init_ch9121();
            RecvFlag = 0;
            ConfigFlag = 0;
            overflow = 0;
        }
        if(RecvFlag == 1 && config_flag == 0)
        {
            RecvFlag = 0;

            net_rx_buf[511] = 0;//避免溢出
            overflow = 0;
            //解析HTTP请求
            memset(&request, 0, sizeof request);
            
            parse_http_request(&request, net_rx_buf);
            memset(net_rx_buf, 0, 511);
            printf_http_request(&request);
            //判断请求是否正确
            if(strcmp(HTTP_VERSION, (const char *)request.request_line.method))
            {
                if(strcmp(HTTP_GET, request.request_line.method) == 0)
                {
                    if(strcmp(PathState, request.request_line.uri.path) == 0)
                    {
                        //memset(&sta, 0, sizeof sta);
                        char *json = JSON_State(sta);
                        tx_data = http_request_respond(HTTP_VERSION, CONTENT_TYPE, 200, json, strlen(json));
                        printf("%s, %d\n",tx_data , strlen(tx_data));  
                        free(json);
                        
                        
                        
                                              
                    }
                    else if(strcmp(PathValue, request.request_line.uri.path) == 0)
                    {
  
                        char * json = centrifugeToJson(&cen);
                        printf("%s, %d\n",json , strlen(json));     
                        tx_data = http_request_respond(HTTP_VERSION, CONTENT_TYPE, 200, json, strlen(json));
                                            
                        free(json);
                    }
                    else if(strcmp(PathRun, request.request_line.uri.path) == 0)
                    {
                        
                        if(strcmp(FromKeyRun, (const char *)(request.request_line.uri.urlf[0].key)) == 0)
                        {
                            int len = atoi((const char *)(request.request_line.uri.urlf[0].value));
                            if(len > 3) len = 3;
                            memset(&runs, 0, 10 *sizeof(RunData));
                            char *json = runDataToJsonString(runs, len);
                            
                        
                            tx_data = http_request_respond(HTTP_VERSION, CONTENT_TYPE, 200, json, strlen(json));
                            printf("%s, %d\n",tx_data , strlen(tx_data));  
                            free(json);
                        }
                        else //全部运行记录
                        {
                            memset(&runs, 0, 10 *sizeof(RunData));
                            char *json = runDataToJsonString(runs, 1);
                            
                            printf("hhhhhhhh\n");
                            tx_data = http_request_respond(HTTP_VERSION, CONTENT_TYPE, 200, json, strlen(json));
                            printf("%s, %d\n",tx_data , strlen(tx_data));  
                            free(json);
                        }
                    }
                    else
                    {
                        tx_data = http_request_respond(HTTP_VERSION, CONTENT_TYPE, 404, HTTP_404, strlen(HTTP_404));
                    }
                }
                else 
                {   
                    tx_data = http_request_respond(HTTP_VERSION, CONTENT_TYPE, 404, HTTP_404, strlen(HTTP_404));
                }
            }
            else 
            {   
                tx_data = http_request_respond(HTTP_VERSION, CONTENT_TYPE, 404, HTTP_404, strlen(HTTP_404));
            }
            Usartx_SendBytes(UART4, tx_data, strlen(tx_data));
            tx_data = NULL;
        }
        RecvFlag = 0;
        os_dly_wait(1);
        
    }
}

具体工程不能直接发到网上,因为这是公司的一个项目,所以有需要的可以联系我给源码文件

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值