Linux下实现Post方式

来源:互联网 发布:宣城太守知不知 编辑:程序博客网 时间:2024/06/05 18:31

首先了解HTTP协议各字段的含义,以下是部分较好的归纳:
HTTP一个HTTP请求报文由请求行(request line)、请求头部(header)、空行和请求数据4个部分组成。

 (1)请求行
请求行由请求方法字段、URL字段和HTTP协议版本字段3个字段组成,它们用空格分隔。例如,GET /index.html HTTP/1.1。
HTTP协议的请求方法有GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT。这里介绍最常用的GET方法和POST方法。
GET:当客户端要从服务器中读取文档时,使用GET方法。GET方法要求服务器将URL定位的资源放在响应报文的数据部分,回送给客户端。使用GET方法时,请求参数和对应的值附加在URL后面,利用一个问号(“?”)代表URL的结尾与请求参数的开始,传递参数长度受限制。例如,/index.jsp?id=100&op=bind。
POST:当客户端给服务器提供信息较多时可以使用POST方法。POST方法将请求参数封装在HTTP请求数据中,以名称/值的形式出现,可以传输大量数据,可用来传送文件。
(2)请求头部
请求头部由关键字/值对组成,每行一对,关键字和值用英文冒号“:”分隔。请求头部通知服务器有关于客户端请求的信息,典型的请求头有:
User-Agent:产生请求的浏览器类型。
Accept:客户端可识别的内容类型列表。
Host:请求的主机名,允许多个域名同处一个IP地址,即虚拟主机。
(3)空行
最后一个请求头之后是一个空行,发送回车符和换行符,通知服务器以下不再有请求头。
对于一个完整的http请求来说空行是必须的,否则服务器会认为本次请求的数据尚未完全发送到服务器,处于等待状态。
(4)请求数据
请求数据不在GET方法中使用,而是在POST方法中使用。POST方法适用于需要客户填写表单的场合。与请求数据相关的最常使用的请求头是Content-Type和Content-Length。
一、Post访问

1、程序分析:

使用socket 编程实现Post访问网页,以TCP协议绑定。

代码如下:


CHTTPClient.hpp:

#ifndef SRC_HTTPCLIENT_HPP
#define SRC_HTTPCLIENT_HPP

#include <netinet/in.h>
#include <sys/socket.h>

typedef struct _httpInfo
{
    int socket;
    int connected;
    int remote_port;
    std::string remote_ip;
    struct sockaddr_in _addr;
} HTTPInfo;

class CHTTPClient
{
public:

    int HTTPClientCreate(HTTPInfo& http);
    int HTTPClientConnect(HTTPInfo& http);
    int HTTPClientSend(const HTTPInfo& http, char *buff, int length);
    int HTTPClientReceive(const HTTPInfo& http, char **lpbuff);
    int HTTPClientClose(HTTPInfo& http);
    int HTTPPost(HTTPInfo& http, char *page, char* type, char *request, long request_len, char **response);
}; //class CHTTPClient

#endif  //SRC_HTTPCLIENT_HPP




CHTTPClient.cpp:

int CHTTPClient::HTTPClientCreate(HTTPInfo& http)
{
    NGILog_Trace("func = %s begins", __FUNCTION__);
    struct hostent *he;

    if (NULL == (he = gethostbyname(http.remote_ip.c_str())))
    {
        NGILog_Error("func = %s ends, hostent pointer is null!", __FUNCTION__);
        return -1;
    }

    char ip[17];
    strcpy(ip, inet_ntoa(*((struct in_addr *) he->h_addr) ));

    http.remote_ip = ip;
    http.connected = 0;
    http._addr.sin_family = AF_INET;
    http._addr.sin_port = htons(http.remote_port);
    http._addr.sin_addr = *((struct in_addr *) he->h_addr);

    if (-1 == (http.socket = socket(AF_INET, SOCK_STREAM, 0)))
    {
        NGILog_Error("func = %s ends, create socket fail!", __FUNCTION__);
        return -2;
    }

    NGILog_Trace("func = %s ends, create socket instance is successful!", __FUNCTION__);
    return 0;
}

int CHTTPClient::HTTPClientConnect(HTTPInfo& http)
{
    NGILog_Trace("func = %s begins", __FUNCTION__);

    if (!http.connected)
    {
        if (connect(http.socket, (struct sockaddr *) &http._addr, sizeof(struct sockaddr)) == -1)
        {
            NGILog_Error("func = %s ends, HTTP client is connect error!", __FUNCTION__);
            return -1;
        }

        http.connected = 1;
    }
    else
    {
        NGILog_Trace("func = %s ends, HTTP client is already existed!", __FUNCTION__);
    }

    NGILog_Trace("func = %s ends, connect socket is successful!", __FUNCTION__);
    return 0;
}

int CHTTPClient::HTTPClientSend(const HTTPInfo& http, char *buff, int length)
{
    NGILog_Trace("func = %s begins, the size of the buffer is %d, buffer data:\n%s", __FUNCTION__, length, buff);

    int bytes_left = length;
    int sent_bytes = 0;
    char *ptr = buff;

    while (bytes_left > 0)
    {
        sent_bytes = send(http.socket, ptr, bytes_left, 0);
        if (sent_bytes <= 0)
        {
            if (errno == EINTR)
            {
                NGILog_Warning("func = %s , interrupts were generated!", __FUNCTION__);
                sent_bytes = 0;
            }
            else
            {
                NGILog_Error("func = %s ends, send data error!", __FUNCTION__);
                return -1;
            }
        }
        bytes_left -= sent_bytes;
        ptr += sent_bytes;
    }

    NGILog_Trace("func = %s ends, send data finish!", __FUNCTION__);
    return 0;
}

int CHTTPClient::HTTPClientReceive(const HTTPInfo& http, char **lpbuff)
{
    NGILog_Trace("func = %s begins", __FUNCTION__);

    int bytes_recv = 0;
    int bytes_buff = 0;
    char buff[BUFFER_SIZE+1];

    *lpbuff = NULL;

    while (1)
    {
        memset(buff, '\0', sizeof(buff));
        bytes_recv = recv(http.socket, buff, BUFFER_SIZE, 0);
        printf ("func = %s, recv size is %d, buff data:\n%s", __FUNCTION__, bytes_recv, buff);
        //NGILog_Trace("func = %s, recv size is %d", __FUNCTION__, bytes_recv);
        if (bytes_recv < 0)
        {
            if (errno == EINTR)
            {
                NGILog_Warning("func = %s , interrupts were generated!", __FUNCTION__);
                bytes_recv = 0;
            }
            else
            {
                NGILog_Error("func = %s ends, receive data error!", __FUNCTION__);
                return -1;
            }
        }
        else if (bytes_recv == 0)
        {
            NGILog_Error("func = %s, receive data finish!", __FUNCTION__);
            break;
        }

        bytes_buff += bytes_recv;

        if (*lpbuff == NULL)
        {
            NGILog_Warning("func = %s , interrupts were generated!", __FUNCTION__);
            *lpbuff = (char*) malloc(bytes_buff);
            if (*lpbuff == NULL)
            {
                return -1;
            }
        }
        else
        {
            NGILog_Trace("func = %s, line = %d", __FUNCTION__, __LINE__);
            *lpbuff = (char*) realloc(*lpbuff, bytes_buff);
            if (*lpbuff == NULL)
            {
                return -2;
            }
        }
        memcpy((*lpbuff + bytes_buff - bytes_recv), buff, bytes_recv);
    }

    printf("func = %s ends, the size of the received data is %d!", __FUNCTION__, strlen(*lpbuff));
    return (strlen(*lpbuff));
}



int CHTTPClient::HTTPClientClose(HTTPInfo& http)
{
    NGILog_Trace("func = %s begins", __FUNCTION__);

    close(http.socket);
    http.connected = 0;

    NGILog_Trace("func = %s ends, close socket finish!", __FUNCTION__);
    return 0;
}

int CHTTPClient::HTTPPost(HTTPInfo& http, char *page, char* type, char *request, long request_len, char **response)
{
    NGILog_Trace("func = %s begins", __FUNCTION__);

    char *lpbuf = NULL;
    char post[strlen(page) + 20], host[http.remote_ip.size() + 20], content_type[strlen(type) + 20], content_len[50];
    memset(post, '\0', sizeof(post));
    memset(host, '\0', sizeof(host));
    memset(content_type, '\0', sizeof(content_type));
    memset(content_len, '\0', sizeof(content_len));

    sprintf(post, "POST %s HTTP/1.1\r\n", page);
    sprintf(host, "HOST: %s:%d\r\n", http.remote_ip.c_str(), http.remote_port);
    sprintf(content_type, "Content-Type: %s\r\n", type);
    sprintf(content_len, "Content-Length: %ld\r\n\r\n", request_len);

    int len = strlen(post) + strlen(host) + strlen(content_type) + strlen(content_len) + request_len + 1;
    char send_data[len];
    memset(send_data, '\0', sizeof(send_data));
    memcpy(send_data, post, strlen(post));
    memcpy(&send_data[strlen(post)], host, strlen(host));
    memcpy(&send_data[strlen(post) + strlen(host)], content_type, strlen(content_type));
    memcpy(&send_data[strlen(post) + strlen(host) + strlen(content_type)], content_len, strlen(content_len));
    memcpy(&send_data[strlen(post) + strlen(host) + strlen(content_type) + strlen(content_len)], request, request_len);
 
    if (HTTPClientCreate(http))
    {
        NGILog_Error("func = %s ends, create socket instance error!", __FUNCTION__);
        return -1;
    }

    if (!http.connected)
    {
        if (HTTPClientConnect(http))
        {
            NGILog_Error("func = %s ends, connect socket error!", __FUNCTION__);
            return -2;
        }
    }

    if (HTTPClientSend(http, send_data, len) < 0)
    {
        NGILog_Error("func = %s ends, send data error!", __FUNCTION__);
        return -3;
    }

    /*it's time to receive data from server*/
    if (HTTPClientReceive(http, response) <= 0)
    {
        NGILog_Error("func = %s ends, receive data error!", __FUNCTION__);
        return -4;
    }

    HTTPClientClose(http);

    printf("func = %s ends, post data is finish, response data:\n%s", __FUNCTION__, *response);
//    NGILog_Trace("func = %s ends, post data is finish, response data:\n%s", __FUNCTION__, *response);
    return 0;
}

原创粉丝点击