• mongoose实现httpserver,client


    使用mongoose来做http协议的基础,基本上的函数都在一个c文件里面,直接包含c文件就可以实现一个httpserve和httpclient,可以实现一个小型的httpserver,要求的并发数不是很高,如下所示,直接将mongoose.c包含在项目里面。

    在这里插入图片描述

    1 server

    首先http server 是一个线程类, 定义一个线程基类,然后httpserver从基类继承下去,使用start函数以后,线程开启,调用run函数,无限循环。server不仅是可以是httpserver,也可以是websocketserver。

    /*
    Author:钱波
    email: 418511899@qq.com
    wei:   18091589062
    func  :线程类
    time:  2018年5月30日
    */
    
    #ifndef _TTHREAD_RUN_ABLE_H_
    #define _TTHREAD_RUN_ABLE_H_
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    using namespace std;
    
    class TThreadRunable
    {
    private:
    
    	//线程
    	thread _thread;
    	//等待信号
    	std::mutex _signal_mutex;
    	std::condition_variable _cond;
    protected:
    	//char  _running = false;
    	char _stop = true;
    	//锁定运行状态
    	std::mutex _mutex;
    public:
    	TThreadRunable()
    	{}
    	virtual ~TThreadRunable()
    	{}
    
    public:
    	char * status(){
    		return &_stop;
    	}
    	
    	void Join()
    	{
    		if (_thread.joinable())
    			_thread.join();
    	}
    	bool  IsStop()
    	{
    		return _stop == 1 ? true : false;
    	}
    
    	void WaitForSignal()
    	{
    		std::unique_lock<std::mutex> ul(_signal_mutex);
    		_cond.wait(ul);
    	}
    	void Notify()
    	{
    		_cond.notify_one();
    	}
    
    	virtual int Start()
    	{
    		if (_stop == 1)//非運行中
    		{
    			_stop = 0;
    			_thread = std::thread(std::bind(&TThreadRunable::Run, this));
    			return 0;
    		}
    		return -1;
    	}	
    	
    	virtual void Stop()
    	{
    		_stop = 1; // true;
    	}
    
    	virtual void Run() = 0;
    };
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82

    实现httpserver,主要是实现httpserver的run函数,实现循环。

    #include "mongoose.h"
    #include "TThreadRunable.h"
    #include 
    #include 
    #include 
    using namespace std;
    //typedef struct re_param
    //{
    //	void * pUser;
    //	string uri;
    //	string host;
    //	string uid;
    //	string message;
    //}re_param;
    //using handler = std::function ;
    typedef struct request_param
    {
    	//返回的
    	string retString;
    	map<string, string> params;
    	void insertParam(string key)
    	{
    		params[key] = "null";
    	}
    	void setParam(string key, string value)
    	{
    		params[key] = value;
    	}
    	const char* getParam(string key)
    	{
    		if (params.find(key) != params.end())
    		{
    			return params[key].c_str();
    		}
    		return NULL;
    	}
    	int getSize()
    	{
    		return (int)params.size();
    	}
    	map<string, string>::iterator iter;
    	const char * GetFirstParam()
    	{
    		iter = params.begin();
    		if (iter == params.end())
    			return NULL;
    		return iter->first.c_str();
    	}
    	void SetParamValue(const char *value)
    	{
    		if (iter != params.end())
    			iter->second = value;
    	}
    
    	const char * GetNextParam()
    	{
    		iter++;
    		if (iter == params.end())
    		{
    			return NULL;
    		}
    		else
    		{
    			return iter->first.c_str();
    		}
    	}
    }request_param;
    
    using handler2 = std::function<void(request_param &rp)>;
    
    typedef struct route_request
    {
    	request_param _param;
    	handler2 func;
    }route_request;
    
    
    class Service_HTTP :public TThreadRunable
    {
    protected:
    	using handler_map = std::map<std::string, route_request>;
    	handler_map _handlers;
    public:
    	//handler handlestart = nullptr;
    	//handler handlestop  = nullptr;
    	//handler hanlde_volume = nullptr;
    	//handler handle_microphone = nullptr;
    	handler_map &GetHandleMap()
    	{
    		return _handlers;
    	}
    
    	const char *s_http_port = "9091";
    	struct mg_serve_http_opts _s_http_server_opts;
    	struct mg_mgr _mgr;
    	struct mg_connection * _nc = NULL;
    
    	bool RegisterHandler(std::string uri, route_request f) {
    		auto it = _handlers.find(uri);
    		if (_handlers.end() != it)
    			return false;
    
    		return _handlers.emplace(uri, f).second;
    	}
    
    
    	void UnRegisterHandler(std::string uri) {
    		auto it = _handlers.find(uri);
    		if (_handlers.end() != it)
    			_handlers.erase(it);
    	}
    
    public:
    
    	//static void handle_api(string uri, struct mg_connection *nc, struct http_message *hm);
    	static void handle_api2(string uri, struct mg_connection *nc, struct http_message *hm);
    
    	static void ev_handler(struct mg_connection *nc, int ev, void *ev_data);
    	static int is_websocket(const struct mg_connection *nc) {
    		return nc->flags & MG_F_IS_WEBSOCKET;
    	}
    
    	
    //广播该视频数据
    	void WebSocket_Broadcast(void * s2);
    	//void WebSocket_Broadcast1(void * pUser, uint8_t * data, int len);
    public:
    	~Service_HTTP()
    	{
    	}
    	void Stop();
    	void Run();
    	
    
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135

    下面是实现文件

    #include "restful_server.h"
    
    
    
    //#include "../CorePhone/TPictureInfo.h"
    
    
    static struct mg_serve_http_opts s_http_server_opts;
    
    
    void Service_HTTP::WebSocket_Broadcast(void *s)
    {
    	//return ;
    	//int jpglen = 0;
    	//videosend2 *s2 = (videosend2 *)s;
    	//char * jpg = NULL;
    	//plus.EncodeRGB2Jpeg((char*)s2->data, s2->w, s2->h, (s2->w)*3, &jpg, jpglen);
    	//struct mg_connection *c;
    	//if (_nc != NULL) {
    	//	for (c = mg_next(_nc->mgr, NULL); c != NULL; c = mg_next(_nc->mgr, c)) {
    	//		if (c == _nc) continue; /* Don't send to the sender. */
    	//		mg_send_websocket_frame(c, WEBSOCKET_OP_BINARY, jpg, jpglen);
    	//	}
    	//}
    	//if (jpg != NULL)
    	//	delete[]jpg;
    }
    
    //void Service_HTTP::WebSocket_Broadcast1(void * pUser, uint8_t * data, int len)
    //{
    //	struct mg_connection *c;
    //	if (pUser == NULL)
    //		return;
    //
    //	if (_nc != NULL) {
    //		for (c = mg_next(_nc->mgr, NULL); c != NULL; c = mg_next(_nc->mgr, c)) {
    //			if (c == pUser)
    //				mg_send_websocket_frame(c, WEBSOCKET_OP_TEXT, data, len);
    //		}
    //	}
    //
    //}
    
    
    void Service_HTTP::handle_api2(string uri, struct mg_connection *nc, struct http_message *hm)
    {
    	Service_HTTP *sh = (Service_HTTP*)nc->user_data;
    	if (sh == NULL)
    		return;
    	handler_map& hmap = sh->GetHandleMap();
    	handler_map::iterator iter;
    	iter = hmap.find(uri);
    	if (iter == hmap.end())
    	{
    		mg_serve_http(nc, hm, s_http_server_opts); /* Serve static content */
    		return;
    	}
    	route_request & rr = iter->second;
    	const char * param = rr._param.GetFirstParam();
    	while (param != NULL)
    	{
    		char buffer[255];
    		mg_get_http_var(&hm->query_string, param, buffer, sizeof(buffer));
    		rr._param.SetParamValue(&buffer[0]);
    		//rr._param.setParam(string(param), string(buffer));
    		param = rr._param.GetNextParam();
    	}
    	
    
    	/* Send headers */
    	//mg_printf(nc, "%s", "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n");
    	mg_send_response_line(nc, 200, "Access-Control-Allow-Origin: *");
    	//允许哪些url可以跨域请求到本域
    	//mg_printf(nc, "Access-Control-Allow-Origin:*\r\n");
    	//允许的请求方法,一般是GET,POST,PUT,DELETE,OPTIONS
    	mg_printf(nc, "Access-Control-Allow-Methods:POST,OPTIONS,GET\r\n");
    	//允许哪些请求头可以跨域
    	mg_printf(nc, "Access-Control-Allow-Headers:x-requested-with,content-type\r\n");
    	if (rr.func != nullptr)
    	{
    		rr.func(rr._param);
    	}
    
    	string	reply = "{\"ret\":0}";
    	if(!rr._param.retString.empty())
    		reply = rr._param.retString;
    	mg_printf(nc, "Content-Type:application/json\r\n");
    	mg_printf(nc, "Content-Length:%u\r\n\r\n%s\r\n", (uint32_t)reply.size(), reply.c_str());
    	//mg_printf(nc, "HTTP/1.1 200 OK\r\niConnection: close\r\nContent-Type: text/html\r\nContent-Length: %u\r\n\r\n%s\r\n",
    	nc->flags |= MG_F_SEND_AND_CLOSE;
    	//mg_send(nc, "", 0);
    }
    #if 0
    void Service_HTTP::handle_api(string uri, struct mg_connection *nc, struct http_message *hm)
    {
    	Service_HTTP *sh = (Service_HTTP*)nc->user_data;
    	if (sh == NULL)
    		return;
    
    	//const char * param = sh->_param.GetFirstParam();
    	if (uri.compare("/start") == 0)
    	{
    		char host[64];
    		char uid[64];
    		char message[64];
    		mg_get_http_var(&hm->query_string, "serverhost", host, sizeof(host));
    		mg_get_http_var(&hm->query_string, "uid", uid, sizeof(uid));
    		mg_get_http_var(&hm->query_string, "message", message, sizeof(message));
    		/* Send headers */
    		//mg_printf(nc, "%s", "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n");
    		mg_send_response_line(nc, 200, "Access-Control-Allow-Origin: *");
    		//允许哪些url可以跨域请求到本域
    		mg_printf(nc, "Access-Control-Allow-Origin:*\r\n");
    		//允许的请求方法,一般是GET,POST,PUT,DELETE,OPTIONS
    		mg_printf(nc, "Access-Control-Allow-Methods:POST\r\n");
    		//允许哪些请求头可以跨域
    		mg_printf(nc, "Access-Control-Allow-Headers:x-requested-with,content-type\r\n");
    		string reply = "{\"result\":0}";
    		mg_printf(nc, "Content-Length:%u\r\n\r\n%s\r\n", (uint32_t)reply.size(), reply.c_str());
    		//mg_printf(nc, "HTTP/1.1 200 OK\r\niConnection: close\r\nContent-Type: text/html\r\nContent-Length: %u\r\n\r\n%s\r\n",
    		nc->flags |= MG_F_SEND_AND_CLOSE;
    		mg_send(nc, "", 0);
    		//mg_printf_http_chunk(nc, "{ \"result\": %ld }", 0);
    		//mg_send_http_chunk(nc, "", 0); /* Send empty chunk, the end of response */
    
    		
    		re_param request;
    		request.uri = uri;
    		request.pUser = NULL;
    		request.host = host;
    		request.uid = uid;
    		request.message = message;
    		if (sh->handlestart != nullptr)
    			sh->handlestart(request);
    		//it->second(request);
    		OutputDebugString(L"start video to");
    		//callback(__void, host, uid, message);
    		
    	}
    	else if (uri.compare("/stop") == 0) //停止
    	{
    		char message[64];
    
    		mg_get_http_var(&hm->query_string, "message", message, sizeof(message));
    		/* Send headers */
    		//mg_printf(nc, "%s", "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n");
    		mg_send_response_line(nc, 200, "Access-Control-Allow-Origin: *");
    		//允许哪些url可以跨域请求到本域
    		mg_printf(nc, "Access-Control-Allow-Origin:*\r\n");
    		//允许的请求方法,一般是GET,POST,PUT,DELETE,OPTIONS
    		mg_printf(nc, "Access-Control-Allow-Methods:POST\r\n");
    		//允许哪些请求头可以跨域
    		mg_printf(nc, "Access-Control-Allow-Headers:x-requested-with,content-type\r\n");
    		string reply = "{\"result\":0}";
    		mg_printf(nc, "Content-Length:%u\r\n\r\n%s\r\n", (uint32_t)reply.size(), reply.c_str());
    		//mg_printf(nc, "HTTP/1.1 200 OK\r\niConnection: close\r\nContent-Type: text/html\r\nContent-Length: %u\r\n\r\n%s\r\n",
    		nc->flags |= MG_F_SEND_AND_CLOSE;
    
    		mg_send(nc, "", 0);
    		//mg_printf(nc, "{ \"result\": %ld }", 0);
    		//mg_send(nc, "", 0);
    		//mg_printf_http_chunk(nc, "{ \"result\": %ld }", 0);
    		//mg_send_http_chunk(nc, "", 0); /* Send empty chunk, the end of response */
    
    		
    			//auto it = sh->GetHandleMap().find(uri);
    			//if (sh->GetHandleMap().end() == it)
    			//	return;
    			re_param request;
    			request.uri = uri;
    			request.pUser = NULL;
    			request.message = message;
    			if(sh->handlestop!=nullptr)
    				sh->handlestop(request);
    			OutputDebugString(L"stop video");
    	}
    	//else if(uri.compare("getmicrophone"))
    	//获取
    }
    #endif
    
    
    
    void Service_HTTP::ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
    	struct http_message *hm = (struct http_message *) ev_data;
    	//传送文件地址和转化的目的地址
    	//   /api/t2pdf
    	switch (ev) {
    
    	case MG_EV_WEBSOCKET_HANDSHAKE_DONE:
    		printf("here connection\n");
    		break;
    	case MG_EV_WEBSOCKET_FRAME: {
    		struct websocket_message *wm = (struct websocket_message *) ev_data;
    		/* New websocket message. Tell everybody. */
    		struct mg_str d = { (char *)wm->data, wm->size };
    		
    		//broadcast(nc, d);
    		break;
    	}
    
    	case MG_EV_HTTP_REQUEST:
    	{
    		string uri = string(hm->uri.p, hm->uri.len);
    		handle_api2(uri, nc, hm);
    		//if (mg_vcmp(&hm->uri, "/start") == 0) {
    		//	handle_api2(uri, nc, hm);
    		//}
    		//else if (mg_vcmp(&hm->uri, "/stop") == 0) {
    		//	handle_api2(uri, nc, hm);
    		//}
    		//else
    		//{
    		//	mg_serve_http(nc, hm, s_http_server_opts); /* Serve static content */
    		//}
    		break;
    	}
    	case MG_EV_CLOSE:
    	{
    		if (is_websocket(nc))
    			OutputDebugString(L"websocket out");
    		break;
    	}
    	default:
    		break;
    	}
    }
    
    
    void Service_HTTP::Stop()
    {
    	TThreadRunable::Stop();
    	Join();
    }
    
    
    
    void Service_HTTP::Run()
    {
    	mg_mgr_init(&_mgr, NULL);
    	_nc = mg_bind(&_mgr, s_http_port, ev_handler);
    	_nc->user_data = this;
    	mg_set_protocol_http_websocket(_nc);
    	s_http_server_opts.document_root = "./public";  // Serve current directory
    	s_http_server_opts.enable_directory_listing = "yes";
    	//printf("Started on port %s\n", s_http_port);
    	while (!IsStop()) {
    		mg_mgr_poll(&_mgr, 50);
    	}
    	mg_mgr_free(&_mgr);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252

    run函数是一个无线while循环,注意mongoose谈不上有太高的效率,实际上就是使用mg_mgr_poll来实现的,每隔50毫秒刷新一次,这个50毫秒可以自行修改。
    调用的时候也可以使用lamba函数,如下所示

    handler hd1 = std::bind(&CMeetingDlg::StartHttpCallback, this, std::placeholders::_1);
    _httpserver.RegisterHandler("/start", hd1);
    
    • 1
    • 2

    下面实现client

    #pragma once
    #include 
    #include 
    
    
    #include "mongoose.h"
    #include "../CorePhone/TThreadRunable.h"
    
    typedef void(*callback_http)(std::string);
    class HttpClient//:public TThreadRunable
    {
    private:
    	mg_connection *connection = NULL;
    	mg_mgr mgr;
    	std::string _posturl;
    public:
    	void seturl(const char * ip)
    	{
    		//string temp = url;
    		_posturl = "http://";
    		_posturl += ip;
    		_posturl += "/streamclose";
    	}
    public:
    	HttpClient();
    	~HttpClient();
    
    	void SendReq();
    	static void OnHttpEvent(mg_connection *connection, int event_type, void *event_data);
    	int s_exit_flag;
    	callback_http s_callback;
    	//void Run();
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    #include "HttpClient.h"
    
    //ReqCallback HttpClient::s_req_callback;
    
    // 客户端的网络请求响应
    void HttpClient::OnHttpEvent(mg_connection *connection, int event_type, void *event_data)
    {
    	HttpClient * hc =(HttpClient *)connection->user_data;
    	http_message *hm = (struct http_message *)event_data;
    	int connect_status;
    
    	switch (event_type)
    	{
    	case MG_EV_CONNECT:
    		connect_status = *(int *)event_data;
    		if (connect_status != 0)
    		{
    			printf("Error connecting to server, error code: %d\n", connect_status);
    			hc->s_exit_flag = 1;
    		}
    		break;
    	case MG_EV_HTTP_REPLY:
    	{
    		printf("Got reply:\n%.*s\n", (int)hm->body.len, hm->body.p);
    		std::string rsp = std::string(hm->body.p, hm->body.len);
    		connection->flags |= MG_F_SEND_AND_CLOSE;
    		hc->s_exit_flag = 1; // 每次收到请求后关闭本次连接,重置标记
    
    		// 回调处理
    		hc->s_callback(rsp);
    	}
    	break;
    	case MG_EV_CLOSE:
    		if (hc->s_exit_flag == 0)
    		{
    			printf("Server closed connection\n");
    			hc->s_exit_flag = 1;
    		};
    		break;
    	default:
    		break;
    	}
    }
    
    
    // 发送一次请求,并回调处理,然后关闭本次连接
    void HttpClient::SendReq()
    {
    	if (_posturl.empty())
    		return;
    
    
    	// 给回调函数赋值
    	//s_callback = req_callback;
    
    	connection = mg_connect_http(&mgr, OnHttpEvent, _posturl.c_str(), NULL, NULL);
    	connection->user_data = this;
    	mg_set_protocol_http_websocket(connection);
    
    	//printf("Send http request %s\n", _posturl.c_str());
    
    	// loop
    	//while (s_exit_flag == 0)
    	mg_mgr_poll(&mgr, 50);
    	mg_mgr_poll(&mgr, 50);
    
    
    }
    HttpClient::HttpClient()
    {
    	mg_mgr_init(&mgr, NULL);
    }
    HttpClient::~HttpClient()
    {
    	mg_mgr_free(&mgr);
    }
    //void HttpClient::Run()
    //{
    //
    //}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80

    简单的server和client 就可以这么简单的实现,不用花费太多精力。

  • 相关阅读:
    Gateway学习和源码解析
    Activiz快速显示大量球体
    Hyperledger Fabric组织的动态添加和删除
    IDEA下使用Spring MVC
    华为OD机试真题 Java 实现【最长公共后缀】【2023 B卷 100分】,等于白送
    SpringCloud 微服务应用篇 | (1)微服务远程调用与Eureka 注册中心
    java毕业设计爱宠医院管理系统mybatis+源码+调试部署+系统+数据库+lw
    投资失败+转岗降薪,2年逆袭月薪30K,我的船终于靠了岸
    Ubuntu下无法输入中文问题解决
    Informer--用于长序列时序预测【2021AAAI Best Paper】
  • 原文地址:https://blog.csdn.net/qianbo042311/article/details/127128950