久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费
標題:
一個簡單的嵌入式平臺httpd服務器源程序
[打印本頁]
作者:
alwaysman
時間:
2019-10-9 17:59
標題:
一個簡單的嵌入式平臺httpd服務器源程序
分享一個簡單地http服務器源代碼,適合于無系統的嵌入式平臺。
0.png
(5.15 KB, 下載次數: 63)
下載附件
2019-10-10 01:16 上傳
源程序如下:
/*
* httpd.c
*
* Created on: 2019年09月01日
* Author: YAO Zhanhong
*/
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <udelay.h>
#include "SPI_W5500/SPI_W5500.h"
#include "html.h"
#include "httpd.h"
#include "httpd_htm.h"
SOCKET l_http_socket = W5500_SOCKET_INVALID;
uint8_t l_request_buffer[HTTP_REQUEST_BUFF_SIZE]; /* Request的緩沖 */
uint16_t l_request_length; /* Request的長度 */
char* l_request_param_list[HTTP_REQUEST_PARAM_MAX]; /* Request的參數列表,指向l_request_buffer中的地址 */
uint16_t l_request_param_num; /* 解析后,Request的參數個數 */
char* l_request_method; /* 解析后,Request的方法 */
char* l_request_URL; /* 解析后,Request的URL */
char* l_request_version; /* 解析后,Request的版本 */
char* l_request_URI; /* 解析后,Request的URI */
char* l_request_content; /* 解析后,Request的正文 */
uint16_t l_request_content_len; /* 實際接收到的正文長度 */
uint16_t l_request_content_len_desired; /* 請求頭中指示的Request的正文長度,即正文應收長度 */
uint16_t l_cur_process_pos; /* 指在Request緩沖中,當前處理到的位置 */
/*****************************************************************************************************************************
* 回調函數,由驅動循環調用,傳遞接收到的socket數據
* 在本函數中,將socket傳遞的數據追加到http服務器的處理緩沖中,具體的協議處理則在http服務器的loop中進行
* 因為一次接收可能無法將Request的全部請求數據傳遞完成,所以需要先緩沖起來,湊成足夠大的request請求數據,在loop中集中處理
* 即使這樣,由于緩沖有限,所以當POST數據超長時,服務器仍會無法處理
*****************************************************************************************************************************/
void on_http_request(SOCKET s_client, uint8_t* data, uint16_t data_len)
{
if ( l_http_socket != s_client )
{
return;
}
if (data != NULL && data_len > 0 )
{
for ( int i = 0; i < data_len; i++ )
{
printf("%c", data[i]);
}
printf("\n");
/* 把接收到的數據添加到request緩沖 */
if ( l_request_length + data_len <= HTTP_REQUEST_BUFF_SIZE )
{
memcpy( l_request_buffer + l_request_length, data, data_len );
l_request_length += data_len;
}
else
{
memcpy( l_request_buffer + l_request_length, data, HTTP_REQUEST_BUFF_SIZE - l_request_length );
l_request_length = HTTP_REQUEST_BUFF_SIZE;
}
}
}
/*****************************************************************************************************************************
* 重置全部request接收變量
*****************************************************************************************************************************/
void reset_request()
{
memset(l_request_buffer, 0, HTTP_REQUEST_BUFF_SIZE);
l_request_length = 0;
for (uint16_t i = 0; i < HTTP_REQUEST_PARAM_MAX; i++ )
{
l_request_param_list[i] = NULL;
}
l_request_param_num = 0;
l_request_method = NULL;
l_request_URL = NULL;
l_request_version = NULL;
l_request_URI = NULL;
l_request_content = NULL;
l_request_content_len = 0;
l_request_content_len_desired = 0;
l_cur_process_pos = 0;
}
/*****************************************************************************************************************************
* 獲取完整的一行
* 返回值:該行的字符總數,包括結尾的回車換行,為0表示未找到結尾的回車換行
*****************************************************************************************************************************/
uint16_t get_line(uint8_t* data, uint16_t data_len)
{
uint16_t ret_len = 0;
if ( data != NULL && data_len >= 2 )
{
for ( uint16_t i = 0; i < data_len - 1; i++ )
{
if ( data[i] == 0x0D && data[i+1] == 0x0A )
{
ret_len = i + 2;
break;
}
}
}
return ret_len;
}
/*****************************************************************************************************************************
* 解析Request的第一行,即:方法/URL/版本
*****************************************************************************************************************************/
void parse_request_first(uint8_t* data, uint16_t data_len, char** method, char** URL, char** version)
{
uint16_t cur_pos = 0;
*method = NULL;
*URL = NULL;
*version = NULL;
if ( data != NULL && data_len >= 2 )
{
*method = (char *)data;
for ( uint16_t i = cur_pos; i < data_len; i++ )
{
if ( data[i] == 0x20 )
{
data[i] = 0;
cur_pos = i + 1;
break;
}
}
*URL = (char *)(data + cur_pos);
for ( uint16_t i = cur_pos; i < data_len; i++ )
{
if ( data[i] == 0x20 )
{
data[i] = 0;
cur_pos = i + 1;
break;
}
}
*version = (char *)(data + cur_pos);
for ( uint16_t i = cur_pos; i < data_len; i++ )
{
if ( data[i] == 0x0D )
{
data[i] = 0;
break;
}
}
}
}
/*****************************************************************************************************************************
* 解析Request頭信息
*****************************************************************************************************************************/
void parse_request_header(uint8_t* data, uint16_t data_len, char** item, char** value)
{
uint16_t cur_pos = 0;
*item = NULL;
*value = NULL;
if ( data != NULL && data_len >= 2 )
{
*item = (char *)data;
for ( uint16_t i = cur_pos; i < data_len; i++ )
{
if ( data[i] == 0x3A ) /* 尋找":" */
{
data[i] = 0;
cur_pos = i + 1;
break;
}
}
*value = (char *)(data + cur_pos);
for ( uint16_t i = cur_pos; i < data_len; i++ )
{
if ( data[i] == 0x0D )
{
data[i] = 0;
break;
}
}
}
}
/*****************************************************************************************************************************
* 解析Request的傳遞參數
*****************************************************************************************************************************/
uint16_t parse_request_parameter(uint8_t* data, uint16_t data_len, char** param_list, uint16_t param_max)
{
uint16_t i;
uint16_t param_num = 0;
uint16_t param_pos = 0;
for ( uint16_t i = 0; i < param_max; i++ )
{
param_list[i] = NULL;
}
if ( data != NULL && data_len >= 0 )
{
while ( param_pos < data_len )
{
if ( param_num >= param_max )
{
break;
}
param_list[param_num] = (char *)(data + param_pos);
for ( i = param_pos; i < data_len; i++ )
{
if ( data[i] == 0x26 ) /* 判斷是否有&符號 */
{
data[i] = 0;
param_pos = i + 1;
param_num++;
break;
}
}
if ( i == data_len )
{
param_num++;
break;
}
}
}
return param_num;
}
/*****************************************************************************************************************************
* 解析Request的URL
*****************************************************************************************************************************/
uint16_t parse_request_URL(uint8_t* data, char** URI, char** param_list, uint16_t param_max)
{
uint16_t i;
uint16_t url_len = 0;
uint16_t param_num = 0;
uint16_t param_pos = 0;
for ( uint16_t i = 0; i < param_max; i++ )
{
param_list[i] = NULL;
}
if ( data != NULL )
{
url_len = (uint16_t)strlen(data);
}
if ( url_len > 0 )
{
*URI = (char *)data;
if( url_len > 1 )
{
param_pos = url_len; /* 默認沒有參數 */
for ( i = 0; i < url_len; i++ )
{
if ( data[i] == 0x3F ) /* 通過查找問號,來判斷是否有參數 */
{
data[i] = 0;
param_pos = i + 1;
break;
}
}
if ( param_pos < url_len )
{
param_num = parse_request_parameter( data + param_pos, url_len - param_pos, param_list, param_max );
}
}
}
return param_num;
}
/**********************************************************************
* 服務器的出錯響應
**********************************************************************/
void http_respond_error(SOCKET s_client, uint16_t err_code)
{
char buf[128];
uint8_t* html_data = NULL;
uint16_t html_file_len = 0;
uint16_t html_send_pos = 0;
uint16_t cur_send_len = 0;
switch (err_code)
{
case 400:
sprintf(buf, "HTTP/1.0 400 Bad Request\r\n");
html_data = g_Respond_400;
html_file_len = sizeof(g_Respond_400);
break;
case 404:
sprintf(buf, "HTTP/1.0 404 Not Found\r\n");
html_data = g_Respond_404;
html_file_len = sizeof(g_Respond_404);
break;
case 501:
sprintf(buf, "HTTP/1.0 501 Method Not Implemented\r\n");
html_data = g_Respond_501;
html_file_len = sizeof(g_Respond_501);
break;
case 505:
sprintf(buf, "HTTP/1.0 505 Nonsupport http Version\r\n");
html_data = g_Respond_505;
html_file_len = sizeof(g_Respond_505);
break;
default:
sprintf(buf, "HTTP/1.0 %d ERROR\r\n", err_code);
}
W5500_send(s_client, buf, strlen(buf));
sprintf(buf, HTTP_SERVER_STRING);
W5500_send(s_client, buf, strlen(buf));
sprintf(buf, "Content-Type: text/html\r\n");
W5500_send(s_client, buf, strlen(buf));
sprintf(buf, "Content-Length: %d\r\n", html_file_len);
W5500_send(s_client, buf, strlen(buf));
sprintf(buf, "\r\n");
W5500_send(s_client, buf, strlen(buf));
if ( html_data != NULL && html_file_len > 0 )
{
while ( html_send_pos < html_file_len )
{
if ( html_send_pos + 500 < html_file_len )
{
cur_send_len = W5500_send(s_client, html_data + html_send_pos, 500);
}
else
{
cur_send_len = W5500_send(s_client, html_data + html_send_pos, html_file_len - html_send_pos );
}
if ( cur_send_len == 0 )
{
break;
}
html_send_pos += cur_send_len;
}
}
}
void server_respond(s_client)
{
char buf[1024];
uint16_t html_file_len = 0;
uint16_t html_send_pos = 0;
uint16_t cur_send_len = 0;
//發送HTTP頭
sprintf(buf, "HTTP/1.0 200 OK\r\n");
W5500_send(s_client, buf, strlen(buf));
sprintf(buf, HTTP_SERVER_STRING);
W5500_send(s_client, buf, strlen(buf));
sprintf(buf, "Content-Type: text/html\r\n");
W5500_send(s_client, buf, strlen(buf));
sprintf(buf, "\r\n");
W5500_send(s_client, buf, strlen(buf));
/*
*
sprintf(buf, "<HTML><HEAD><TITLE>MESH Node Configuration Site</TITLE></HEAD>\r\n");
W5500_send(s_client, buf, strlen(buf));
sprintf(buf, "<BODY bgcolor=\"BLUE\">\r\n");
W5500_send(s_client, buf, strlen(buf));
sprintf(buf, "<form action=\"/config\" method=\"POST\">用戶名:<input type=\"text\" name=\"test_name\"><br /><br />密 碼:<input type=\"text\" name=\"test_pwd\"><br /><br /><input type=\"submit\"><form>\r\n");
W5500_send(s_client, buf, strlen(buf));
sprintf(buf, "</BODY></HTML>\r\n");
W5500_send(s_client, buf, strlen(buf));
* */
html_file_len = sizeof(g_HTML_index);
while ( html_send_pos < html_file_len )
{
if ( html_send_pos + 500 < html_file_len )
{
cur_send_len = W5500_send(s_client, g_HTML_index + html_send_pos, 500);
}
else
{
cur_send_len = W5500_send(s_client, g_HTML_index + html_send_pos, html_file_len - html_send_pos );
}
html_send_pos += cur_send_len;
}
}
bool http_process_request(SOCKET s_client, char* URI, char** param_list, uint16_t param_num )
{
bool result = false;
if ( strcasecmp(URI, "/") == 0 )
{
server_respond(s_client);
result = true;
}
else if ( strcasecmp(URI, "/config") == 0 )
{
//result = true;
}
return result;
}
/**********************************************************************
* 服務器的loop
**********************************************************************/
void HTTP_loop()
{
char* requeset_header_item = NULL;
char* requeset_header_item_value = NULL;
uint16_t cur_request_line_len = 0;
bool result = false;
/* 如果緩沖包達到最大處理長度,則直接返回錯誤,關閉連接 */
if ( l_request_length == HTTP_REQUEST_BUFF_SIZE )
{
/* 格式錯誤,請求包數據超過處理上限 */
http_respond_error(l_http_socket, 400);
W5500_socket_TCP_close(l_http_socket);
reset_request();
return;
}
/* 判斷當前是否正在接收正文 */
if ( l_request_content_len_desired > 0 )
{
/* 正在接收正文,此時僅增加正文長度即可 */
l_request_content_len += l_request_length - l_cur_process_pos;
l_cur_process_pos = l_request_length;
if ( l_request_content_len < l_request_content_len_desired )
{
/* 還沒達到預期的正文長度,結束本次循環,待下次處理 */
return;
}
else if ( l_request_content_len > l_request_content_len_desired )
{
/* 格式錯誤,實際接收的正文長度已經超過請求頭中的正文長度 */
http_respond_error(l_http_socket, 400);
W5500_socket_TCP_close(l_http_socket);
reset_request();
return;
}
else
{
/* 實際接收的正文長度與請求頭中的正文長度一致,則繼續處理 */
result = true;
}
}
else
{
/* 把需要的信息全都解析出來 */
while ( l_cur_process_pos < l_request_length )
{
/* 提取一行,獲得該行長度 */
cur_request_line_len = get_line( l_request_buffer + l_cur_process_pos, l_request_length - l_cur_process_pos );
if ( cur_request_line_len > 2 )
{
/* 如果是第一行,則解析方法、URL和版本號 */
if ( l_cur_process_pos == 0 )
{
parse_request_first(l_request_buffer, cur_request_line_len, &l_request_method, &l_request_URL, &l_request_version);
}
else
{
/* 解析請求頭信息 */
parse_request_header( l_request_buffer + l_cur_process_pos, cur_request_line_len, &requeset_header_item, &requeset_header_item_value );
if( requeset_header_item != NULL && requeset_header_item_value != NULL )
{
/* 必須至少解析正文長度 */
if ( strcasecmp(requeset_header_item, "Content-Length") == 0 )
{
sscanf(requeset_header_item_value, "%hu", &l_request_content_len_desired);
}
}
}
l_cur_process_pos += cur_request_line_len;
}
else if ( cur_request_line_len == 2 ) /* 這是一個空行,默認有消息正文 */
{
l_cur_process_pos += cur_request_line_len;
/* 如果空行之后還有數據,那就是正文 */
if ( l_cur_process_pos < l_request_length )
{
l_request_content = (char *)(l_request_buffer + l_cur_process_pos );
l_request_content_len = l_request_length - l_cur_process_pos;
}
}
else
{
/* 沒有找到行,那說明已經達到最末端 */
l_cur_process_pos = l_request_length;
}
}
if ( l_request_content_len > 0 )
{
if ( l_request_content_len_desired == 0 )
{
/* 格式錯誤,請求頭未包含正文數據長度 */
http_respond_error(l_http_socket, 400);
W5500_socket_TCP_close(l_http_socket);
reset_request();
return;
}
else
{
if ( l_request_content_len < l_request_content_len_desired )
{
/* 直接結束本次循環,待下次處理 */
return;
}
else if ( l_request_content_len > l_request_content_len_desired )
{
/* 格式錯誤,實際接收的正文長度已經超過請求頭中的正文長度 */
http_respond_error(l_http_socket, 400);
W5500_socket_TCP_close(l_http_socket);
reset_request();
return;
}
else
{
/* 實際接收的正文長度與請求頭中的正文長度一致,則繼續處理 */
result = true;
}
}
}
else
{
if ( l_request_content_len_desired > 0 )
{
/* 格式錯誤,請求頭中的正文長度 不為0,但接收的正文長度為0 */
http_respond_error(l_http_socket, 400);
W5500_socket_TCP_close(l_http_socket);
reset_request();
return;
}
else
{
/* 實際接收的正文長度與請求頭中的正文長度一致,則繼續處理 */
result = true;
}
}
}
/* 進行http響應,必須有請求數據,并且正文接收處理完成 */
if ( result && l_request_length > 0 )
{
/* 判斷方法、URL和版本號是否正確 */
if ( l_request_method != NULL && strlen(l_request_method) > 0 &&
l_request_URL != NULL && strlen(l_request_URL) > 0 &&
l_request_version != NULL && strlen(l_request_version) > 0 )
{
if ( strcasecmp(l_request_version, "HTTP/0.9") == 0 ||
strcasecmp(l_request_version, "HTTP/1.0") == 0 ||
strcasecmp(l_request_version, "HTTP/1.1") == 0 )
{
/* 解析URL,獲取URI,獲取參數 */
l_request_param_num = parse_request_URL((uint8_t *)l_request_URL, &l_request_URI, l_request_param_list, HTTP_REQUEST_PARAM_MAX);
/* 根據解析結果進行處理 */
if ( strcasecmp(l_request_method, "GET") == 0 )
{
result = true;
}
else if ( strcasecmp(l_request_method, "POST") == 0 )
{
/* 解析正文,獲取參數 */
l_request_param_num = parse_request_parameter((uint8_t *)l_request_content, l_request_content_len, l_request_param_list, HTTP_REQUEST_PARAM_MAX);
result = true;
}
else
{
result = false;
}
/* 可以處理 */
if ( result )
{
result = http_process_request(l_http_socket, l_request_URI, l_request_param_list, l_request_param_num);
if ( !result )
{
/* 沒有發現資源 */
http_respond_error(l_http_socket, 501);
}
}
else
{
/* 僅僅實現了GET和POST */
http_respond_error(l_http_socket, 501);
}
}
else
{
/* 不支持的版本 */
http_respond_error(l_http_socket, 505);
}
}
else
{
/* 格式錯誤 */
http_respond_error(l_http_socket, 400);
}
/* 傳輸完成后,必須要切斷連接 */
W5500_socket_TCP_close(l_http_socket);
reset_request();
}
}
/**********************************************************************
* 初始化,主程序調用
**********************************************************************/
void HTTP_init(SOCKET s)
{
reset_request();
if ( W5500_socket_TCP_Server( s, HTTP_SERVER_PORT_DEFAULT, on_http_request ) )
{
W5500_socket_TCP_listen( s );
l_http_socket = s;
}
}
復制代碼
所有資料51hei提供下載:
httpd.rar
(4.62 KB, 下載次數: 8)
2019-10-9 17:58 上傳
點擊文件名下載附件
http服務器源代碼
下載積分: 黑幣 -5
作者:
wofei1314
時間:
2019-10-17 11:44
謝謝分享~
歡迎光臨 (http://www.zg4o1577.cn/bbs/)
Powered by Discuz! X3.1
主站蜘蛛池模板:
亚洲日本欧美日韩高观看
|
久久久九九九九
|
久久精品国产免费一区二区三区
|
国产精品国产成人国产三级
|
精品久久久久久久久亚洲
|
国产免费让你躁在线视频
|
日韩精品一区二区三区免费视频
|
欧美日韩国产在线
|
日韩欧美在线观看
|
黄色a视频
|
久久久久9999
|
欧美在线一区二区视频
|
天天操 夜夜操
|
亚洲欧美综合精品久久成人
|
欧美国产激情
|
高清一区二区三区
|
天天干夜夜拍
|
久久国产精品视频免费看
|
国产欧美视频一区二区
|
97国产在线视频
|
久久久精品一区
|
亚洲一区
|
久久精品视频在线播放
|
欧美精产国品一二三区
|
精品国产91乱码一区二区三区
|
三级视频网站
|
黄色一级片视频
|
国产伦一区二区三区久久
|
亚洲一区二区在线免费观看
|
国产精品日韩一区二区
|
亚洲永久字幕
|
中文字幕高清免费日韩视频在线
|
久久久99国产精品免费
|
国产高清自拍视频在线观看
|
97色在线视频
|
亚洲高清在线观看
|
亚洲国产成人精品女人久久久
|
av一区二区三区四区
|
超碰在线久
|
少妇精品亚洲一区二区成人
|
在线免费观看视频你懂的
|