从硬件底层通信看http协议和https协议的数据流

     嵌入式硬件与服务器的通信常常采用http协议或是https协议,实际上https协议就是http协议+SSL加密通信,简单点说就是把http协议的数据经过一定的算法加密后发送出去,接收方收到后再解密出来。http协议是运行在tcp协议的上一层,也就是说协议数据是在TCP数据的流的基础上再进行编码获得。接触过以太网底层编程的同学都熟悉socket编程,那么一段数据按http协议进行编码,调用write()函数写入网络socket上,对方收到的数据就是http数据。

      http协议是一种无连接,无状态的连接协议,无连接的意思是说,需要通信时才建议连接(TCP连接),通信完成后一般关闭链接。无状态协议的话就是一次性,只有一个状态,不像TCP协议一样,通信过程中有各种状态之间依次变换才能完成通信。协议对话的发起由客户端发出请求给服务器,服务器根据客户端发来的数据进行响应。

客户端请求消息

客户端发送一个HTTP请求到服务器的请求消息包括以下格式:请求行(request line)、请求头部(header)、空行和请求数据四个部分组成,下图给出了请求报文的一般格式。

2012072810301161


服务器响应消息

     HTTP响应由四部分组成,分别是状态行、消息报头,空行和响应正文。

从硬件底层通信看http协议和https协议的数据流_第1张图片

      http协议占用TCP通信的80端口号,https协议通信占用TCP通信的443端口号。上面只是介绍了协议,可能你还是不太明白网络上的数据流是什么样子的。一个示例如下:

/*请百度服务器*/
#define SIMPLE_GET_REQUEST \
    "GET / HTTP/1.1\r\n" \
    "Host: www.baidu.com\r\n" \
    "Connection: close\r\n" \
    "\r\n"
/*简单的HTTP请求*/
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 rcv_buf[1024];
    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 ) )
    {
    n= read(client_fd, rcv_buf, sizeof(rcv_buf))
   }
}


void main(void)
{
    simple_http_get("www.baidu.com", SIMPLE_GET_REQUEST);
}

      通过上面的示例就不难看出,http请求百度服务器就是发出一个GET请求了,请求的编码就是按照协议写一些字符串以换行结尾,之后把这些编码好的字符串通过write()函数写入到百度服务器的80端口上就可以了。

"GET / HTTP/1.1\r\n" \
    "Host: www.baidu.com\r\n" \
    "Connection: close\r\n" \
    "\r\n"


你可能感兴趣的:(编程经验)