C++ 简单实现HTTP GET/POST 请求
HTTP(超文本传输协议)是一种客户端与服务端的传输协议,最早用于浏览器和服务器之间的通信,后来因为其使用灵活、方便等特点,广泛用于客户端与服务端的通信。文章将简单介绍HTTP协议,同时以C++方式分别实现HTTP GET、POST 请求
HTTP 请求报文
HTTP请求报文的一般格式由4部分组成:请求行、请求头部、空行、请求数据。如下图所示:
1.jpg
请求行:包含3部分内容:请求方法,URL,协议版本。形式如:GET /?aaa=1 HTTP/1.1。请求方法有GET、POST、HEAD、PUT、DELETE、OPTIONS等。URL指请求服务端的地址,可以是相对地址或域名形式的绝对地址。协议版本主要有HTTP/1.1 HTTP/1.0 HTTP/0.9,后面两种已很少使用了。
请求头部:以key/value形式成对表示头部参数,以英文冒号分隔。key名称的约定写法为Key,Key-Name,自定义key名称一般以“X-”开头。如php的声明“X-Powered-By:PHP/5.5.4-1”
空行:用来标识请求头部的数据已结束。
请求数据:可选项,这块内容只在POST方式下使用,作为POST的数据表示区域。使用这块内容,要在请求头部以Content-Length声明请求数据长度,以Content-Type声明请求数据类型。
HTTP POST请求
HTTP POST方式是把请求参数放到HTTP请求报文的请求数据中,为了让例子更容易看懂,仅保留HTTP Post关键参数,你还可以自定义一些参数,比如浏览器喜欢用的User-Agent,Accept,Connection等等
char *pHttpPost = "POST %s HTTP/1.1\r\n"
"Host: %s:%d\r\n"
"Content-Type: application/x-www-form-urlencoded\r\n"
"Content-Length: %d\r\n\r\n"
"%s";
char* addr = "http://localhost/post.php";
char* host = "127.0.0.1";
int port = 80;
char* msg = "aaa=1&bbb=2";
char strHttpPost[1024] = {0};
sprintf(strHttpPost, pHttpPost, addr, host, port, strlen(msg), msg);
//这里忽略掉了socket连接代码
send(sockClient, strHttpPost, strlen(strHttpPost), 0);
HTTP GET请求
HTTP GET方式是把请求参数放到HTTP请求报文的请求行URL中,所以请求行就是“GET /?aaa=1&bbb=2 HTTP/1.1\r\n”。URL最大长度通常浏览器取255,这和文件路径最大长度有关。虽然HTTP允许更大长度,但不建议怎么做,如果太长了,可以考虑换成POST方式
char *pHttpGet = "GET %s?%s HTTP/1.1\r\n"
"Host: %s:%d\r\n\r\n";
char* addr = "http://localhost/get.php";
char* host = "127.0.0.1";
int post = 80;
char* msg = "aaa=1&bbb=2";
char strHttpGet[1024] = {0};
sprintf(strHttpGet, pHttpGet, addr, msg, host, post);
//这里忽略掉了socket连接代码
send(sockClient, strHttpGet, strlen(strHttpGet), 0);
实现的HTTP
#include "HttpConnect.h"
#ifdef WIN32
#pragma comment(lib,"ws2_32.lib")
#endif
HttpConnect::HttpConnect()
{
#ifdef WIN32
//此处一定要初始化一下,否则gethostbyname返回一直为空
WSADATA wsa = { 0 };
WSAStartup(MAKEWORD(2, 2), &wsa);
#endif
}
HttpConnect::~HttpConnect()
{
}
void HttpConnect::socketHttp(std::string host, std::string request)
{
int sockfd;
struct sockaddr_in address;
struct hostent *server;
sockfd = socket(AF_INET,SOCK_STREAM,0);
address.sin_family = AF_INET;
address.sin_port = htons(80);
server = gethostbyname(host.c_str());
memcpy((char *)&address.sin_addr.s_addr,(char*)server->h_addr, server->h_length);
if(-1 == connect(sockfd,(struct sockaddr *)&address,sizeof(address))){
DBG <<"connection error!"<
HttpConnect *http = new HttpConnect();
http->getData("127.0.0.1", "/login", "id=liukang&pw=123");
http->postData("127.0.0.1", "/login","id=liukang&pw=123");
我的第一个段落。
//***********************************
C++实现简单http服务器
只要懂socket套接字,http请求和响应的格式,就行了
#include
#include
#include
#include
#pragma comment(lib,"ws2_32.lib")
using namespace std;
#define PORT 9999
int main(){
SOCKET sock;
SOCKET connfd;
WORD ver = MAKEWORD(2,2);//版本
WSADATA dat;
WSAStartup(ver, &dat);
sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (sock == -1)
{
return false;
}
struct sockaddr_in sever_address;
memset(&sever_address,0,sizeof(sever_address));
sever_address.sin_family = AF_INET;
sever_address.sin_addr.s_addr =htonl(INADDR_ANY);
sever_address.sin_port = htons(PORT);
int ret = bind(sock, (struct sockaddr*)&sever_address,sizeof(sever_address));
assert(ret != -1);
ret = listen(sock,10);
assert(ret != -1);
cout<<"wait\n";
while (1)
{
struct sockaddr_in client_address;
int len=sizeof client_address;
connfd=accept(sock,(sockaddr*)&client_address,&len);
char buf[1024];
int n=recv(connfd,buf,sizeof buf,0);
buf[n]='\0';
printf("recv:\n%s\n",buf);
char head[]="HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n";
string text1="\n\n\n
string text2="我的第一个标题
\n
string text=text1+text2;
send(connfd,head,strlen(head),0);
send(connfd,text.c_str(),strlen(text.c_str()),0);
printf("send:\n");
cout<
closesocket(connfd);
}
closesocket(sock);
getchar();
}
//********************************
C++ http服务器和客户端代码(无报文格式)
服务器代码
SOCKET clientSocket=socket(AF_INET,SOCK_STREAM,0);
int send_len = 0;
int recv_len = 0;
//定义服务端套接字,接受请求套接字
SOCKET s_server;
//服务端地址客户端地址
SOCKADDR_IN server_addr;
//初始化套接字库
WSADATA wsadata;
WSAStartup(0x22, &wsadata);
//填充服务端地址信息
//填充服务端信息
server_addr.sin_family = AF_INET;
server_addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
server_addr.sin_port = htons(80);
std::string msgstr="";
//创建套接字
s_server = socket(AF_INET, SOCK_STREAM, 0);
int result = bind(s_server,(struct sockaddr *) &server_addr,sizeof(server_addr));
if (result == SOCKET_ERROR) /* 绑定失败 */
{
closesocket(s_server);
printf("[Web] Fail to bind, error = %d\n", WSAGetLastError());
return -1;
}
if (listen(s_server,SOMAXCONN)==-1) {
int err = GetLastError();
std::cout << "服务器启动失败!" << std::endl;
std::cout << err << std::endl;
}
else {
std::cout << "服务器启动成功!" << std::endl;
}
while(1){
SOCKADDR_IN from_addr; /* 客户端地址 */
socklen_t from_len = sizeof(from_addr);
std::string reponse_data="404";
SOCKET acpt_soc = accept(s_server,(struct sockaddr *) &from_addr,&from_len);
if (acpt_soc == INVALID_SOCKET) /* 接受失败 */
{ int err = GetLastError();
printf("接收失败1", WSAGetLastError());
std::cout << err << std::endl;
break;
}
char recv_buf [1025] = "";
recv_len = recv(acpt_soc,recv_buf,1025, 0);
if (recv_len < 0) {
std::cout << "接收失败2!" << std::endl;
}else{
std::cout << "接收成功!" << std::endl;
std::cout << recv_buf << std::endl;
}
send_len = send(acpt_soc,recv_buf,strlen(recv_buf), 0);
if (send_len < 0) {
std::cout << "发送失败!" << std::endl;
closesocket(acpt_soc);
}else{
std::cout << "发送成功!" << std::endl;
}
}
//关闭套接字
closesocket(s_server);
//释放DLL资源
WSACleanup();
客户端代码
SOCKET clientSocket=socket(AF_INET,SOCK_STREAM,0);
//printf("客户端嵌套字已经打开!\n");
int send_len = 0;
int recv_len = 0;
//定义服务端套接字,接受请求套接字
SOCKET s_server;
//服务端地址客户端地址
SOCKADDR_IN server_addr;
//初始化套接字库
WSADATA wsadata;
WSAStartup(0x22, &wsadata);
//填充服务端地址信息
//填充服务端信息
server_addr.sin_family = AF_INET;
server_addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
server_addr.sin_port = htons(12580);
string msgstr="";
//创建套接字
s_server = socket(AF_INET, SOCK_STREAM, 0);
int nTimeout = 120000;
//设置接收超时为1000ms
if (SOCKET_ERROR == setsockopt(s_server, SOL_SOCKET, SO_RCVTIMEO, (char *)&nTimeout, sizeof(int)))
{
fprintf(stderr, "Set SO_RCVTIMEO error !\n");
}
if (connect(s_server, (SOCKADDR *)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR) {
cout << "服务器连接失败!" << endl;
closesocket(s_server);
//释放DLL资源
WSACleanup();
return 0;
}
else {
cout << "服务器连接成功!" << endl;
}
//发送,接收数据
cout << "开始传输桌面信息:"<< endl;
while(1){
char send_buf [1025] = "111";
send_len = send(s_server,send_buf,strlen(send_buf), 0);
if (send_len < 0) {
cout << "发送失败!" << endl;
closesocket(s_server);
//释放DLL资源
WSACleanup();
return 0;
}else{
cout << "发送成功!" << endl;
}
char recv_buf [1025] = "";
recv_len = recv(s_server,recv_buf,1025, 0);
if (recv_len < 0) {
cout << "接收失败!" << endl;
closesocket(s_server);
//释放DLL资源
WSACleanup();
return 0;
}else{
cout <
}
}
//关闭套接字
closesocket(s_server);
//释放DLL资源
WSACleanup();
//************************************
C++实现简单的HTTP服务器
#include