服务端与客户端简单例子
官网
官网有详细的说明和丰富的例子,有兴趣的可以去看看
服务端
http_server_sample
#include "mongoose.h"
static const char *s_http_port = "8000";
static void ev_handler(struct mg_connection *c, int ev, void *p) {
if (ev == MG_EV_HTTP_REQUEST) {
struct http_message *hm = (struct http_message *) p;
// We have received an HTTP request. Parsed request is contained in `hm`.
// Send HTTP reply to the client which shows full original request.
//我们收到一个HTTP请求。解析后的请求包含在“hm”中。
//向显示完整原始请求的客户端发送HTTP回复。
//(int)hm->message.len, hm->message.p 中存放客户端发过来的信息,包括post,Host(http地址),Content-Length(信息的长度),以及信息本身。
//通过 std::string url = std::string(hm->uri.p, hm->uri.len); 可以得到url
//通过 std::string body = std::string(hm->body.p, hm->body.len);可以得到body中 存储的从客户端发送过来的信息
mg_send_head(c, 200, hm->message.len, "Content-Type: text/plain");
mg_printf(c, "%.*s", (int)hm->message.len, hm->message.p);
}
}
int main(void) {
//mg_mgr是拥有所有活动连接的事件管理器
struct mg_mgr mgr;
//mg_connection描述连接
struct mg_connection *c;
//初始化
mg_mgr_init(&mgr, NULL);
//连接
c = mg_bind(&mgr, s_http_port, ev_handler);
//http
mg_set_protocol_http_websocket(c);
for (;;) {
//mg_mgr_poll()遍历所有套接字,接受新连接,发送和接收数据,关闭连接并为相应事件调用事件处理函数
mg_mgr_poll(&mgr, 1000);
}
mg_mgr_free(&mgr);
return 0;
}
mg_connect()呼叫建立呼出连接。mg_bind()通话会建立监听连接。入站连接是侦听连接接受的连接。每个连接都由该struct mg_connection 结构描述,该结构具有许多字段,例如套接字,事件处理函数,发送/接收缓冲区,标志等。
ev_handler(事件处理函数)
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
switch (ev) {
/* Event handler code that defines behavior of the connection */
...
}
}
struct mg_connection *nc:已收到事件的连接。
int ev:事件编号,在中定义mongoose.h。例如,当数据到达入站连接时,ev将为MG_EV_RECV。
void *ev_data:此指针指向事件特定的数据,并且对于不同的事件具有不同的含义。例如,对于一个MG_EV_RECV事件,它 ev_data是一个int *指针,指向从远程对等方接收并保存到接收IO缓冲区中的字节数。ev_data针对每个事件描述了的确切含义 。协议特定的事件通常 ev_data指向保存协议特定信息的结构。
注意:struct mg_connection具有void *user_data用于特定于应用程序的数据的占位符。mongoose不使用该指针。事件处理程序可以在其中存储任何类型的信息。
常用函数
mg_send_head
//发送标头
mg_send_head(struct mg_connection *c, int status_code,
int64_t content_length, const char *extra_headers)
mg_printf
//发送字符串
mg_printf(struct mg_connection *conn, const char *fmt, ...)
mg_send_http_chunk
mg_send_http_chunk(struct mg_connection *nc, const char *buf, size_t len)
使用分块HTTP编码buf将大小大小的缓冲区发送len到客户端。此函数首先以十六进制数字+换行符的形式发送缓冲区大小,然后是缓冲区本身,然后是换行符。
例如, mg_send_http_chunk(nc, "foo", 3)将3\r\nfoo\r\n字符串附加到nc->send_mbuf输出IO缓冲区。
注意:在使用此功能之前,应发送HTTP标头“ Transfer-Encoding:chunked”。
注意:不要忘记在响应的末尾发送一个空块,以告知客户端所有内容均已发送。
mg_printf_http_chunk(nc, "%s", "my response!");
mg_send_http_chunk(nc, "", 0); // Tell the client we're finished
mg_printf_http_chunk
//发送一个printf格式的HTTP块。功能类似于mg_send_http_chunk()
mg_printf_http_chunk(struct mg_connection *nc, const char *fmt, ...)
客户端
http_client_example
#include "mongoose.h"
static const char *url = "http://www.google.com";
static int exit_flag = 0;
static void ev_handler(struct mg_connection *c, int ev, void *p) {
if (ev == MG_EV_HTTP_REPLY) {
struct http_message *hm = (struct http_message *)p;
c->flags |= MG_F_CLOSE_IMMEDIATELY;
//同理,hm->message.len, hm->message.p存放着服务端发送过来的信息,包括post,Host(http地址),Content-Length(信息的长度),以及信息本身。
//通过std::string rsp = std::string(hm->body.p, hm->body.len);
fwrite(hm->message.p, 1, (int)hm->message.len, stdout);
putchar('\n');
exit_flag = 1;
} else if (ev == MG_EV_CLOSE) {
exit_flag = 1;
};
}
int main(void) {
struct mg_mgr mgr;
mg_mgr_init(&mgr, NULL);
mg_connect_http(&mgr, ev_handler, url, NULL, NULL);
while (exit_flag == 0) {
mg_mgr_poll(&mgr, 1000);
}
mg_mgr_free(&mgr);
return 0;
}
mg_connect_http
mg_connect_http(struct mg_mgr *mgr,
mg_event_handler_t ev_handler,
const char *url,
const char *extra_headers,
const char *post_data)
值得注意的是 post_data为发送给服务端的信息