wsclientpp增加http client

1 wsclientpp

wsclientpp是在前面几天写的一个websocket的客户端,缺少纯http协议的客户端,为此而写。
git地址:地址

2 httpcliennt

只实现get协议和post协议,一发一收,还不完善,先写get协议,比较简单,凑字符串参数为host,port, path,和get_content, path为主要路由,get_content 为路径

2.1 get

int getData(const char* host, unsigned short port, const char* path, const char* get_content)
	{
    
    
		//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: cool duck /1.1.1\r\n";
		stream << "Connection:close\r\n\r\n";
		//string temp = stream.str();
		//cout << "len is " << temp.size() << endl;
		return Http(host, port, stream.str().c_str());
	}

2.2 post

依然是post

	int postData(const char* host, unsigned short port, const char* path, const char* post_content)
	{
    
    
		//POST请求方式
		std::stringstream stream;
		stream << "POST " << path;
		stream << " HTTP/1.0\r\n";
		stream << "Host: " << host << "\r\n";
		stream << "User-Agent: cool duck/1.1.1\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 Http(host, port, stream.str().c_str());
	}

2.3 http 函数

int Http(const char* host, unsigned short port, const char *request)
	{
    
    
		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
			cout << "connection error!" << std::endl;
			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
		_data.clear();
#define BUF_SIZE 128
		char buf[128+1];
		//char * buf = new char[64];
		int offset = 0;
		int rc;

		do {
    
    
			int buflen = BUF_SIZE - offset;
			if (buflen == 0)
			{
    
    
				printf("not enough mem,so continue\n");
				offset = 0;
				buflen = BUF_SIZE;
				//break;
			}
#ifdef WIN32
			rc = recv(sockfd, buf + offset, buflen, 0);
			//rc = recv(sockfd, buf + offset, buflen, MSG_WAITALL);
#else
			rc = read(sockfd, buf + offset, 1024);
#endif
			if (rc > 0) {
    
    
				offset += rc;
				buf[rc] = '\0';
				_data += buf;
				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
		cout << _data << endl;
		//buf[offset] = 0;
		//printf("%s\n", buf);
		//_data = buf;
		//delete[]buf;
#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
	}

2.4 增加回调函数

定义回调

typedef void(*callback_http_recv)(void* pUser,const char* message, int len);

类中增加设置函数

void setcallback(callback_http_recv recv,void* puser)
	{
    
    
		v_recv = recv;
		v_puser = puser;
	}

在httpclient 中close之前调用回调

	cout << _data << endl;
	if (v_recv != NULL)
		v_recv(v_puser, _data.c_str, (int)_data.size());

也就是说,我们接收的是纯返回的http内容,还没有解析,下一步要加上解析,所以还不完善,主要需要和wsclientpp 一样,修改成select方式,现在还是阻塞模式,测试程序也没有封装多,也没有放入回调函数,先加入wsclientpp库中,依然是一个头文件,以下是测试程序

#include <iostream>
#include "../CorePhone/httpclient.h"
#ifdef _WIN32
#pragma comment(lib,"ws2_32")
#endif
int main()
{
    
    
	http_connect conn;
	conn.getData("127.0.0.1", 8000, "/", NULL);
	conn.getData("127.0.0.1", 8000, "/test", NULL);
	getchar();
	//std::cout << "Hello World!\n";
}

写一个nodejs的http server 测试,以后还是用python写,这次还是用node

var express = require('express');
var app = express();
var http = require('http').Server(app);
var httpget = require('http');
//var bodyParser = require('body-parser');
var session = require('express-session');

//var rw = require('./config.js');

//在线
//app.use(bodyParser.urlencoded({ extended: false }))
//app.use(bodyParser.json());

app.use(session({
    
    
    secret: 'secret',
    resave: true,// don't save session if unmodified
    saveUninitialized: false,// don't create session until something stored
    cookie: {
    
    
        maxAge: 1000 * 60 * 10 //过期时间设置(单位毫秒)
    }
}));


app.use(express.static(__dirname));

 app.get("/",function(req,res){
    
    
     
     res.send("{ret:ok}");
 });

http.listen(8000, function () {
    
    
    console.log('listening on *:8000');
});

读者自行修改,进行测试,现在吗,http和websocket client都有了。

git地址:地址

猜你喜欢

转载自blog.csdn.net/qianbo042311/article/details/130667879