httpclient 手写

http client c++ 代码

为何手写

### 很多c ,c++ 的获取http协议内容,get或者post 的时候,会犯难,是自己写还是使用现成的库,动辄编译一个库是比较消耗时间的,
能自己手写就不要随便编译库了。
#include 
#include 
#ifdef _WIN32
#include 
#endif
using namespace std;
//获取content-length 的长度,截取
int contentlen_get(char * pos, char * end)
{
	char buf[16];
	char * t = pos;
	while (*(t) == ' ')
		t++;
	char * e = t;
	int i = 0;
	while ((*e) != '\r')
	{
		buf[i++] = *e;
		e++;
		if (i > 14)
			return -1;
	}
	buf[i] = '\0';
	return atoi(buf);
	//return 0;
}

class http_connect
{
public:

	http_connect::http_connect()
	{
#ifdef _WIN32
		//此处一定要初始化一下,否则gethostbyname返回一直为空
		WSADATA wsa = { 0 };
		WSAStartup(MAKEWORD(2, 2), &wsa);
#endif
	}

	http_connect::~http_connect()
	{
		WSACleanup();
	}
	int http_connect::socketHttp(const char* host, unsigned short port, 
		const char *request,char *buf, int buflen)
	{
		SOCKET sockfd;
		struct sockaddr_in address;
		struct hostent *server;

		sockfd = socket(AF_INET, SOCK_STREAM, 0);
		address.sin_family = AF_INET;
		address.sin_port = htons(port);
		//getaddrinfo()
		server = gethostbyname(host);
		memcpy((char *)&address.sin_addr.s_addr, (char*)server->h_addr, server->h_length);

#ifdef _WIN32
		int ret = 0;
		//int timeout = 2000; //2s
		//这样做在Linux环境下是不会产生效果的,须如下定义:
		struct timeval timeout = { 2,0 };
		//设置发送超时
		setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(struct timeval));
		//设置接收超时
		setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval));


		//		ret = setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&timeout, sizeof(timeout));
		//		ret = setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));
#endif
		if (-1 == connect(sockfd, (struct sockaddr *)&address, sizeof(address))) {
#ifdef _WIN32 
			closesocket(sockfd);
#endif
			printf("connection error!\n");
			return -1;
		}



#ifdef WIN32
		int iRes = send(sockfd, request, (int)strlen(request), 0);
		if (iRes == SOCKET_ERROR) {
			printf("send failed: %d\n", WSAGetLastError());
			closesocket(sockfd);
			return -1;
		}
#else
		struct timeval timeout = { 2,0 };//2s
		int ret = setsockopt(sock_fd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&timeout, sizeof(timeout));
		int ret = setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));
		write(sockfd, request, strlen(request));
#endif
		//char * buf = new char[64 * 1024];
		int offset = 0;
		int rc = 0;
		do {
			buflen = buflen - offset;
			if (buflen > 0)
			{
#ifdef WIN32
				rc = recv(sockfd, buf + offset, buflen, MSG_WAITALL);
#else
				rc = read(sockfd, buf + offset, 1024);
#endif
			}
			if (rc > 0) {
				offset += rc;
				printf("Bytes received: %d\n", rc);
			}
			else if (rc == 0)
			{
				printf("Connection closed\n");
			}
			else
			{
				printf("recv failed: %d\n", rc);
			}
		} while (rc > 0);

#ifdef WIN32
		closesocket(sockfd);
#else
		close(sockfd);
#endif
		buf[offset] = 0;
		const char * content_length = strstr(buf, "Content-Length:");
		const char * pos = strstr(buf, "\r\n\r\n");
		if (content_length == NULL  || pos == NULL)
		{
			return -1;
		}
		else
		{
			content_length += 15;
			int len = contentlen_get(" 8\r\n", NULL);
			if (len <= 0)
			{
				return -1;
			}
			//while()
			pos += 4;
			strncpy(buf, pos, len);
			buf[len] = '\0';
			printf("%s\n", pos);
		}

		return 0;
#if 0
		size_t r = _data.rfind("\r\n\r\n");
		cout << "r is " << r << endl;
		//cout << _data << std::endl;
		string re = _data.substr(409 + 4);
		cout << "the re is " << re << endl;
#endif
	}

	int http_connect::postData(const char* host, 
		unsigned short port, 
		const char* path, 
		const char* post_content,char *buf, int buflen)
	{
		//POST请求方式
		std::stringstream stream;
		stream << "POST " << path;
		stream << " HTTP/1.0\r\n";
		stream << "Host: " << host << "\r\n";
		stream << "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3\r\n";
		stream << "Content-Type:application/json\r\n";
		//stream << "Content-Type:application/x-www-form-urlencoded\r\n";
		stream << "Content-Length:" << strlen(post_content) << "\r\n";
		stream << "Connection:close\r\n\r\n";
		stream << post_content;
		//string temp = stream.str();
		//cout << "temp is :" << temp << endl;

		return socketHttp(host, port, stream.str().c_str(),buf, buflen);
	}

	int http_connect::getData(const char* host, unsigned short port, 
		const char* path, 
		const char* get_content,char * buf, int buflen)
	{
		//GET请求方式
		std::stringstream stream;
		if (get_content != NULL && strlen(get_content) > 0)
			//if (strlen(get_content) > 0)
			stream << "GET " << path << "?" << get_content;
		else
			stream << "GET " << path;
		stream << " HTTP/1.0\r\n";
		stream << "Host: " << host << "\r\n";
		stream << "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3\r\n";
		stream << "Connection:close\r\n\r\n";
		//string temp = stream.str();
		//cout << "len is " << temp.size() << endl;
		return socketHttp(host, port, stream.str().c_str(),buf,buflen);
	}
};

以上为基本class ,如何调用,比较简单

int main(int argc, char* argv[])
{
	//int a = contentlen_get(" 8\r\n", NULL);
	//printf("%d\n", a);

	char buffer[10240];
	http_connect hc;
	if (hc.getData("127.0.0.1", 80, "/test", NULL, buffer, 10240) == 0)
	{
		printf("receive json:");
		printf(buffer);
	}
	else
	{
		printf("连接错误");
	}
	return 0;
}

你可能感兴趣的:(http协议)