MiCO 为 HTTP 通信提供了一系列 API 功能接口,主要包括:
实现:设备配网后,可访问 百度一下 网页信息。代码如下:
#include "mico.h"
#include "HTTPUtils.h"
#include "SocketUtils.h"
#include "StringUtils.h"
#define http_client_log(M, ...) custom_log("HTTP", M, ##__VA_ARGS__)
static OSStatus onReceivedData( struct _HTTPHeader_t * httpHeader,
uint32_t pos,
uint8_t *data,
size_t len,
void * userContext );
static void onClearData( struct _HTTPHeader_t * inHeader, void * inUserContext );
static mico_semaphore_t wait_sem = NULL;
typedef struct _http_context_t
{
char *content;
uint64_t content_length;
} http_context_t;
void simple_http_get( char* host, char* query );
void simple_https_get( char* host, char* query );
#define SIMPLE_GET_REQUEST
"GET / HTTP/1.1rn"
"Host: www.baidu.comrn"
"Connection: closern"
"rn"
static void micoNotify_WifiStatusHandler( WiFiEvent status, void* const inContext )
{
UNUSED_PARAMETER( inContext );
switch ( status )
{
case NOTIFY_STATION_UP:
mico_rtos_set_semaphore( &wait_sem );
break;
case NOTIFY_STATION_DOWN:
case NOTIFY_AP_UP:
case NOTIFY_AP_DOWN:
break;
}
}
int application_start( void )
{
OSStatus err = kNoErr;
mico_rtos_init_semaphore( &wait_sem, 1 );
/*Register user function for MiCO nitification: WiFi status changed */
err = mico_system_notify_register( mico_notify_WIFI_STATUS_CHANGED,
(void *) micoNotify_WifiStatusHandler, NULL );
require_noerr( err, exit );
/* Start MiCO system functions according to mico_config.h */
err = mico_system_init( mico_system_context_init( 0 ) );
require_noerr( err, exit );
/* Wait for wlan connection*/
mico_rtos_get_semaphore( &wait_sem, MICO_WAIT_FOREVER );
http_client_log( "wifi connected successful" );
/* Read http data from server */
simple_http_get( "www.baidu.com", SIMPLE_GET_REQUEST );
simple_https_get( "www.baidu.com", SIMPLE_GET_REQUEST );
exit:
mico_rtos_delete_thread( NULL );
return err;
}
void simple_http_get( char* host, char* query )
{
OSStatus err;
int client_fd = -1;
fd_set readfds;
char ipstr[16];
struct sockaddr_in addr;
HTTPHeader_t *httpHeader = NULL;
http_context_t context = { NULL, 0 };
struct hostent* hostent_content = NULL;
char **pptr = NULL;
struct in_addr in_addr;
hostent_content = gethostbyname( host );
require_action_quiet( hostent_content != NULL, exit, err = kNotFoundErr);
pptr=hostent_content->h_addr_list;
in_addr.s_addr = *(uint32_t *)(*pptr);
strcpy( ipstr, inet_ntoa(in_addr));
http_client_log("HTTP server address: %s, host ip: %s", host, ipstr);
/*HTTPHeaderCreateWithCallback set some callback functions */
httpHeader = HTTPHeaderCreateWithCallback( 1024, onReceivedData, onClearData, &context );
require_action( httpHeader, exit, err = kNoMemoryErr );
client_fd = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
addr.sin_family = AF_INET;
addr.sin_addr = in_addr;
addr.sin_port = htons(80);
err = connect( client_fd, (struct sockaddr *)&addr, sizeof(addr) );
require_noerr_string( err, exit, "connect http server failed" );
/* Send HTTP Request */
send( client_fd, query, strlen( query ), 0 );
FD_ZERO( &readfds );
FD_SET( client_fd, &readfds );
select( client_fd + 1, &readfds, NULL, NULL, NULL );
if ( FD_ISSET( client_fd, &readfds ) )
{
/*parse header*/
err = SocketReadHTTPHeader( client_fd, httpHeader );
switch ( err )
{
case kNoErr:
PrintHTTPHeader( httpHeader );
err = SocketReadHTTPBody( client_fd, httpHeader );/*get body data*/
require_noerr( err, exit );
/*get data and print*/
http_client_log( "Content Data: %s", context.content );
break;
case EWOULDBLOCK:
case kNoSpaceErr:
case kConnectionErr:
default:
http_client_log("ERROR: HTTP Header parse error: %d", err);
break;
}
}
exit:
http_client_log( "Exit: Client exit with err = %d, fd: %d", err, client_fd );
SocketClose( &client_fd );
HTTPHeaderDestory( &httpHeader );
}
void simple_https_get( char* host, char* query )
{
OSStatus err;
int client_fd = -1;
int ssl_errno = 0;
mico_ssl_t client_ssl = NULL;
fd_set readfds;
char ipstr[16];
struct sockaddr_in addr;
HTTPHeader_t *httpHeader = NULL;
http_context_t context = { NULL, 0 };
struct hostent* hostent_content = NULL;
char **pptr = NULL;
struct in_addr in_addr;
hostent_content = gethostbyname( host );
require_action_quiet( hostent_content != NULL, exit, err = kNotFoundErr);
pptr = hostent_content->h_addr_list;
in_addr.s_addr = *(uint32_t *)(*pptr);
strcpy( ipstr, inet_ntoa(in_addr));
http_client_log("HTTP server address: host:%s, ip: %s", host, ipstr);
/*HTTPHeaderCreateWithCallback set some callback functions */
httpHeader = HTTPHeaderCreateWithCallback( 1024, onReceivedData, onClearData, &context );
require_action( httpHeader, exit, err = kNoMemoryErr );
client_fd = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
addr.sin_family = AF_INET;
addr.sin_addr = in_addr;
addr.sin_port = htons(443);
err = connect( client_fd, ( struct sockaddr * )&addr, sizeof(addr) );
require_noerr_string( err, exit, "connect http server failed" );
ssl_set_client_version(TLS_V1_2_MODE);
client_ssl = ssl_connect( client_fd, 0, NULL, &ssl_errno );
require_string( client_ssl != NULL, exit, "ERROR: ssl disconnect" );
/* Send HTTP Request */
ssl_send( client_ssl, query, strlen( query ) );
FD_ZERO( &readfds );
FD_SET( client_fd, &readfds );
select( client_fd + 1, &readfds, NULL, NULL, NULL );
if ( FD_ISSET( client_fd, &readfds ) )
{
/*parse header*/
err = SocketReadHTTPSHeader( client_ssl, httpHeader );
switch ( err )
{
case kNoErr:
PrintHTTPHeader( httpHeader );
err = SocketReadHTTPSBody( client_ssl, httpHeader );/*get body data*/
require_noerr( err, exit );
/*get data and print*/
http_client_log( "Content Data: %s", context.content );
break;
case EWOULDBLOCK:
case kNoSpaceErr:
case kConnectionErr:
default:
http_client_log("ERROR: HTTP Header parse error: %d", err);
break;
}
}
exit:
http_client_log( "Exit: Client exit with err = %d, fd: %d", err, client_fd );
if ( client_ssl ) ssl_close( client_ssl );
SocketClose( &client_fd );
HTTPHeaderDestory( &httpHeader );
}
/*one request may receive multi reply*/
static OSStatus onReceivedData( struct _HTTPHeader_t * inHeader, uint32_t inPos, uint8_t * inData,
size_t inLen, void * inUserContext )
{
OSStatus err = kNoErr;
http_context_t *context = inUserContext;
if ( inHeader->chunkedData == false )
{ //Extra data with a content length value
if ( inPos == 0 && context->content == NULL )
{
context->content = calloc( inHeader->contentLength + 1, sizeof(uint8_t) );
require_action( context->content, exit, err = kNoMemoryErr );
context->content_length = inHeader->contentLength;
}
memcpy( context->content + inPos, inData, inLen );
} else
{ //extra data use a chunked data protocol
http_client_log("This is a chunked data, %d", inLen);
if ( inPos == 0 )
{
context->content = calloc( inHeader->contentLength + 1, sizeof(uint8_t) );
require_action( context->content, exit, err = kNoMemoryErr );
context->content_length = inHeader->contentLength;
} else
{
context->content_length += inLen;
context->content = realloc( context->content, context->content_length + 1 );
require_action( context->content, exit, err = kNoMemoryErr );
}
memcpy( context->content + inPos, inData, inLen );
}
exit:
return err;
}
/* Called when HTTPHeaderClear is called */
static void onClearData( struct _HTTPHeader_t * inHeader, void * inUserContext )
{
UNUSED_PARAMETER( inHeader );
http_context_t *context = inUserContext;
if ( context->content )
{
free( context->content );
context->content = NULL;
}
}
上一篇:4.3 文件系统
下一篇:4.1 Socket 通信
版权所有 © 2017 - 2018 MXCHIP授权代理商 - 深圳市博易特智能科技有限公司 粤ICP备17063559号
服务热线:0755-23733662 Email:info@mxchip.cc