Linux下实现Post方式
首先了解HTTP协议各字段的含义,以下是部分较好的归纳:HTTP一个HTTP请求报文由请求行(request line)、请求头部(header)、空行和请求数据4个部分组成。 (1)请求行请求行由请求方法字段、URL字段和HTTP协议版本字段3个字段组成,它们用空格分隔。例如,GET /index.html HTTP/1.1。HTTP协议的请求方法有GET、POST、HE
首先了解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;
}
更多推荐
所有评论(0)