Web服务器系列相关文章编写如下:
官网地址:
https://libevent.org/
libevent - 一个事件通知库。
目前,libevent支持 /dev/poll、 kqueue(2)、 event ports、 POSIX select(2)、 Windows select()、 poll(2)和epoll(4)。内部事件机制完全独立于暴露的事件 API,简单更新 libevent 即可提供新功能,而无需重新设计应用程序。结果,Libevent允许可移植的应用程序开发,并提供操作系统上可用的最具可扩展性的事件通知机制。Libevent 也可以用于多线程应用程序,通过隔离每个 event_base 以便只有单个线程访问它,或者通过锁定对单个共享 event_base 的访问。 Libevent应该在 Linux、*BSD、Mac OS X、Solaris、Windows 等上编译。
Libevent 还为缓冲网络 IO 提供了一个复杂的框架,支持套接字、过滤器、速率限制、SSL、零拷贝文件传输和 IOCP。Libevent 包括对几个有用协议的支持,包括 DNS、HTTP 和最小的 RPC 框架。
官网地址:
https://curl.se/libcurl/
libcurl - 多协议文件传输库.
libcurl 是一个免费且易于使用的客户端 URL 传输库,支持 DICT、FILE、FTP、FTPS、GOPHER、GOPHERS、HTTP、HTTPS、IMAP、IMAPS、LDAP、LDAPS、MQTT、POP3、POP3S、RTMP、 RTMPS、RTSP、SCP、SFTP、SMB、SMBS、SMTP、SMTPS、TELNET 和 TFTP。libcurl 支持 SSL 证书、HTTP POST、HTTP PUT、FTP 上传、基于 HTTP 表单的上传、代理、HTTP/2、HTTP/3、cookies、用户+密码认证(Basic、Digest、NTLM、Negotiate、Kerberos)、文件传输恢复,http代理隧道等等!
libcurl 是高度可移植的,它可以在多种平台上构建和工作,包括 Solaris、NetBSD、FreeBSD、OpenBSD、Darwin、HPUX、IRIX、AIX、Tru64、Linux、UnixWare、HURD、Windows、Amiga、OS/2、BeOs、Mac OS X、Ultrix、QNX、OpenVMS、RISC OS、Novell NetWare、DOS 等…
libcurl 是免费的、线程安全的、与 IPv6 兼容、功能丰富、支持良好、速度快、文档完整,并且已被许多知名、大型和成功的公司使用。
详细介绍请查看本人另外一篇文章:
https://blog.csdn.net/hhy321/article/details/125922276
cJSON是一个使用C语言编写的JSON数据解析器,具有超轻便,可移植,单文件的特点,使用MIT开源协议。
https://github.com/DaveGamble/cJSON
mkdir build
cd build
cmake ..
# or
cmake .. -DENABLE_CJSON_UTILS=On -DENABLE_CJSON_TEST=Off
{
"name": "Awesome 4K",
"resolutions": [
{
"width": 1280,
"height": 720
},
{
"width": 1920,
"height": 1080
},
{
"width": 3840,
"height": 2160
}
]
}
//create a monitor with a list of supported resolutions
//NOTE: Returns a heap allocated string, you are required to free it after use.
char *create_monitor(void)
{
const unsigned int resolution_numbers[3][2] = {
{1280, 720},
{1920, 1080},
{3840, 2160}
};
char *string = NULL;
cJSON *name = NULL;
cJSON *resolutions = NULL;
cJSON *resolution = NULL;
cJSON *width = NULL;
cJSON *height = NULL;
size_t index = 0;
cJSON *monitor = cJSON_CreateObject();
if (monitor == NULL)
{
goto end;
}
name = cJSON_CreateString("Awesome 4K");
if (name == NULL)
{
goto end;
}
/* after creation was successful, immediately add it to the monitor,
* thereby transferring ownership of the pointer to it */
cJSON_AddItemToObject(monitor, "name", name);
resolutions = cJSON_CreateArray();
if (resolutions == NULL)
{
goto end;
}
cJSON_AddItemToObject(monitor, "resolutions", resolutions);
for (index = 0; index < (sizeof(resolution_numbers) / (2 * sizeof(int))); ++index)
{
resolution = cJSON_CreateObject();
if (resolution == NULL)
{
goto end;
}
cJSON_AddItemToArray(resolutions, resolution);
width = cJSON_CreateNumber(resolution_numbers[index][0]);
if (width == NULL)
{
goto end;
}
cJSON_AddItemToObject(resolution, "width", width);
height = cJSON_CreateNumber(resolution_numbers[index][1]);
if (height == NULL)
{
goto end;
}
cJSON_AddItemToObject(resolution, "height", height);
}
string = cJSON_Print(monitor);
if (string == NULL)
{
fprintf(stderr, "Failed to print monitor.\n");
}
end:
cJSON_Delete(monitor);
return string;
}
/* return 1 if the monitor supports full hd, 0 otherwise */
int supports_full_hd(const char * const monitor)
{
const cJSON *resolution = NULL;
const cJSON *resolutions = NULL;
const cJSON *name = NULL;
int status = 0;
cJSON *monitor_json = cJSON_Parse(monitor);
if (monitor_json == NULL)
{
const char *error_ptr = cJSON_GetErrorPtr();
if (error_ptr != NULL)
{
fprintf(stderr, "Error before: %s\n", error_ptr);
}
status = 0;
goto end;
}
name = cJSON_GetObjectItemCaseSensitive(monitor_json, "name");
if (cJSON_IsString(name) && (name->valuestring != NULL))
{
printf("Checking monitor \"%s\"\n", name->valuestring);
}
resolutions = cJSON_GetObjectItemCaseSensitive(monitor_json, "resolutions");
cJSON_ArrayForEach(resolution, resolutions)
{
cJSON *width = cJSON_GetObjectItemCaseSensitive(resolution, "width");
cJSON *height = cJSON_GetObjectItemCaseSensitive(resolution, "height");
if (!cJSON_IsNumber(width) || !cJSON_IsNumber(height))
{
status = 0;
goto end;
}
if ((width->valuedouble == 1920) && (height->valuedouble == 1080))
{
status = 1;
goto end;
}
}
end:
cJSON_Delete(monitor_json);
return status;
}
{
name: "tomcat",
age: "21",
city: "beijing"
}
/*--------------------------------------------------*/
cJSON *root = cJSON_CreateObject();
cJSON_AddStringToObject(root, "name", "tomcat");
cJSON_AddStringToObject(root, "age", "21");
cJSON_AddStringToObject(root, "city", "beijing");
char* str_json = cJSON_Print(root);
printf("构建:%s\n", str_json);
cJSON_Delete(root);
root = NULL;
/*--------------------------------------------------*/
cJSON *root2;
root2 = cJSON_Parse(str_json);
cJSON *result = cJSON_GetObjectItem(root2, "name");
if(result) printf("解析name:%s\n", result->valuestring);
result = cJSON_GetObjectItem(root2, "age");
if (result) printf("解析age:%s\n", result->valuestring);
result = cJSON_GetObjectItem(root2, "city");
if (result) printf("解析city:%s\n", result->valuestring);
https://github.com/libevent/libevent
# WATCH OUT! This makefile is a work in progress. It is probably missing
# tons of important things. DO NOT RELY ON IT TO BUILD A GOOD LIBEVENT.
# Needed for correctness
CFLAGS=/IWIN32-Code /Iinclude /Icompat /DWIN32 /DHAVE_CONFIG_H /I.
# For optimization and warnings
CFLAGS=$(CFLAGS) /Ox /W3 /wd4996 /nologo
# XXXX have a debug mode
LIBFLAGS=/nologo
CORE_OBJS=event.obj buffer.obj bufferevent.obj bufferevent_sock.obj \
bufferevent_pair.obj listener.obj evmap.obj log.obj evutil.obj \
strlcpy.obj signal.obj bufferevent_filter.obj evthread.obj \
bufferevent_ratelim.obj evutil_rand.obj
WIN_OBJS=win32select.obj evthread_win32.obj buffer_iocp.obj \
event_iocp.obj bufferevent_async.obj
EXTRA_OBJS=event_tagging.obj http.obj evdns.obj evrpc.obj
ALL_OBJS=$(CORE_OBJS) $(WIN_OBJS) $(EXTRA_OBJS)
STATIC_LIBS=libevent_core.lib libevent_extras.lib libevent.lib
all: static_libs tests
static_libs: $(STATIC_LIBS)
libevent_core.lib: $(CORE_OBJS) $(WIN_OBJS)
lib $(LIBFLAGS) $(CORE_OBJS) $(WIN_OBJS) /out:libevent_core.lib
libevent_extras.lib: $(EXTRA_OBJS)
lib $(LIBFLAGS) $(EXTRA_OBJS) /out:libevent_extras.lib
libevent.lib: $(CORE_OBJS) $(WIN_OBJS) $(EXTRA_OBJS)
lib $(LIBFLAGS) $(CORE_OBJS) $(EXTRA_OBJS) $(WIN_OBJS) /out:libevent.lib
clean:
del $(ALL_OBJS)
del $(STATIC_LIBS)
cd test
$(MAKE) /F Makefile.nmake clean
tests:
cd test
$(MAKE) /F Makefile.nmake
cd C:\Users\tomcat\Desktop\libevent-2.0.22-stable.tar\libevent-2.0.22-stable
nmake Makefile.nmake
考虑到lib文件区分有md、mdd、mt、mtd所以我们在编译前,修改makefile.nmake文件:
CFLAGS=$(CFLAGS) /Ox /MD /W3 /wd4996 /nologo
CFLAGS=$(CFLAGS) /Ox /MDD /W3 /wd4996 /nologo
CFLAGS=$(CFLAGS) /Ox /MT /W3 /wd4996 /nologo
CFLAGS=$(CFLAGS) /Ox /MTD /W3 /wd4996 /nologo
nmake /f makefile.nmake clean
nmake /f makefile.nmake static_libs
#include
#include
#include
#pragma comment(lib, "libevent\\libevent.lib")
#pragma comment(lib, "libevent\\libevent_core.lib")
#pragma comment(lib, "libevent\\libevent_extras.lib")
/*
cd libevent-2.0.22-stable
nmake /f makefile.nmake static_libs
如果想重新编译:
nmake /f makefile.nmake clean
nmake /f makefile.nmake static_libs
Vs2008命令提示和Vs2008 X64 Win64命令提示,一个是编译32位一个是编译64位。
考虑到lib文件区分有md、mdd、mt、mtd所以我们在编译前,修改makefile.nmake文件:
CFLAGS=$(CFLAGS) /Ox /W3 /wd4996 /nologo
CFLAGS=$(CFLAGS) /Ox /MD /W3 /wd4996 /nologo
CFLAGS=$(CFLAGS) /Ox /MT /W3 /wd4996 /nologo
*/
/*
A trivial static http webserver using Libevent's evhttp.
This is not the best code in the world, and it does some fairly stupid stuff
that you would never want to do in a production webserver. Caveat hackor!
*/
/* Compatibility for possible missing IPv6 declarations */
#include "../util-internal.h"
#include
#include
#include
#include
#include
#ifdef WIN32
#include
#include
#include
#include
#include
#ifndef S_ISDIR
#define S_ISDIR(x) (((x) & S_IFMT) == S_IFDIR)
#endif
#else
#include
#include
#include
#include
#include
#include
#endif
#include
#include
#include
#include
#include
#ifdef _EVENT_HAVE_NETINET_IN_H
#include
# ifdef _XOPEN_SOURCE_EXTENDED
# include
# endif
#endif
/* Compatibility for possible missing IPv6 declarations */
#include "../util-internal.h"
#ifdef WIN32
//#define stat _stat
//#define fstat _fstat
//#define open _open
//#define close _close
//#define O_RDONLY _O_RDONLY
#endif
char uri_root[512];
static const struct table_entry {
const char *extension;
const char *content_type;
} content_type_table[] = {
{ "txt", "text/plain" },
{ "c", "text/plain" },
{ "h", "text/plain" },
{ "html", "text/html" },
{ "htm", "text/htm" },
{ "css", "text/css" },
{ "gif", "image/gif" },
{ "jpg", "image/jpeg" },
{ "jpeg", "image/jpeg" },
{ "png", "image/png" },
{ "pdf", "application/pdf" },
{ "ps", "application/postsript" },
{ NULL, NULL },
};
int from_hex(char ch)
{
return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
}
std::string UrlUnescapeString(const std::string& s)
{
std::istringstream ss(s);
std::string result;
std::getline(ss, result, '%');
std::string buffer;
while (std::getline(ss, buffer, '%'))
{
if (buffer.size() >= 2)
{
result += char((from_hex(buffer[0]) << 4) | from_hex(buffer[1])) + buffer.substr(2);
}
}
return result;
}
/* Try to guess a good content-type for 'path' */
static const char *
guess_content_type(const char *path)
{
const char *last_period, *extension;
const struct table_entry *ent;
last_period = strrchr(path, '.');
if (!last_period || strchr(last_period, '/'))
goto not_found; /* no exension */
extension = last_period + 1;
for (ent = &content_type_table[0]; ent->extension; ++ent) {
if (!evutil_ascii_strcasecmp(ent->extension, extension))
return ent->content_type;
}
not_found:
return "application/misc";
}
/* Callback used for the /dump URI, and for every non-GET request:
* dumps all information to stdout and gives back a trivial 200 ok */
static void
dump_request_cb(struct evhttp_request *req, void *arg)
{
const char *cmdtype;
struct evkeyvalq *headers;
struct evkeyval *header;
struct evbuffer *buf;
switch (evhttp_request_get_command(req)) {
case EVHTTP_REQ_GET: cmdtype = "GET"; break;
case EVHTTP_REQ_POST: cmdtype = "POST"; break;
case EVHTTP_REQ_HEAD: cmdtype = "HEAD"; break;
case EVHTTP_REQ_PUT: cmdtype = "PUT"; break;
case EVHTTP_REQ_DELETE: cmdtype = "DELETE"; break;
case EVHTTP_REQ_OPTIONS: cmdtype = "OPTIONS"; break;
case EVHTTP_REQ_TRACE: cmdtype = "TRACE"; break;
case EVHTTP_REQ_CONNECT: cmdtype = "CONNECT"; break;
case EVHTTP_REQ_PATCH: cmdtype = "PATCH"; break;
default: cmdtype = "unknown"; break;
}
printf("Received a %s request for %s\nHeaders:\n",
cmdtype, evhttp_request_get_uri(req));
headers = evhttp_request_get_input_headers(req);
for (header = headers->tqh_first; header;
header = header->next.tqe_next) {
printf(" %s: %s\n", header->key, header->value);
}
buf = evhttp_request_get_input_buffer(req);
puts("Input data: <<<");
while (evbuffer_get_length(buf)) {
int n;
char cbuf[128];
n = evbuffer_remove(buf, cbuf, sizeof(cbuf));
if (n > 0)
(void) fwrite(cbuf, 1, n, stdout);
}
puts(">>>");
evhttp_send_reply(req, 200, "OK", NULL);
}
/* This callback gets invoked when we get any http request that doesn't match
* any other callback. Like any evhttp server callback, it has a simple job:
* it must eventually call evhttp_send_error() or evhttp_send_reply().
*/
sPluginNotify m_notify;
sHttpParam mParam;
static void
send_document_cb(struct evhttp_request *req, void *arg)
{
struct evbuffer *evb = NULL;
const char *docroot = (const char *)arg;
const char *uri = evhttp_request_get_uri(req);
struct evhttp_uri *decoded = NULL;
const char *path;
char *decoded_path;
char *whole_path = NULL;
size_t len;
int fd = -1;
struct stat st;
if (evhttp_request_get_command(req) != EVHTTP_REQ_GET) {
dump_request_cb(req, arg);
return;
}
if (uri == NULL) {
return;
}
printf("Got a GET request for <%s>\n", uri);
if (strstr(uri, "favicon.ico")) {
return;
}
/* Decode the URI */
decoded = evhttp_uri_parse(uri);
if (!decoded) {
printf("It's not a good URI. Sending BADREQUEST\n");
evhttp_send_error(req, HTTP_BADREQUEST, 0);
return;
}
std::string uri_ansi = UrlUnescapeString(uri);
FxLib::Type::CUtf8Buffer str_utf8(uri_ansi.c_str());
uri = str_utf8.Get();
/* Let's see what path the user asked for. */
path = evhttp_uri_get_path(decoded);
if (!path) path = "/";
/* We need to decode it, to see what path the user really wanted. */
decoded_path = evhttp_uridecode(path, 0, NULL);
if (decoded_path == NULL)
goto err;
/* Don't allow any ".."s in the path, to avoid exposing stuff outside
* of the docroot. This test is both overzealous and underzealous:
* it forbids aceptable paths like "/this/one..here", but it doesn't
* do anything to prevent symlink following." */
if (strstr(decoded_path, ".."))
goto err;
/* This holds the content we're sending. */
evb = evbuffer_new();
/
const char* name_prefix = strstr(uri, "name=");
if (name_prefix == NULL) {
goto err;
}
printf("client: %s\n", uri);
evhttp_add_header(evhttp_request_get_output_headers(req),
"Content-Type", "text/html;charset=gb2312");
evbuffer_add_printf(evb, "\n");
if(uri != NULL) evbuffer_add_printf(evb, uri);
if (name_prefix && name_prefix + 5 != NULL) {
evbuffer_add_printf(evb, "
\n");
evbuffer_add_printf(evb, name_prefix + 5);
}
evbuffer_add_printf(evb, "\n");
evhttp_send_reply(req, 200, "OK", evb);
/
goto done;
err:
evhttp_send_error(req, 404, "Document was not found");
if (fd>=0)
close(fd);
done:
if (decoded)
evhttp_uri_free(decoded);
if (decoded_path)
free(decoded_path);
if (whole_path)
free(whole_path);
if (evb)
evbuffer_free(evb);
}
static void
syntax(void)
{
fprintf(stdout, "Syntax: http-server \n" );
}
DWORD WINAPI https_createServer(LPVOID lpParam)
{
struct event_base *base;
struct evhttp *http;
struct evhttp_bound_socket *handle;
//
unsigned short port = (unsigned short)lpParam;
if(port == 0) {
std::string dllPath = "C:\\Config\\";
if (!::PathFileExists(dllPath.c_str())) {
::CreateDirectory(dllPath.c_str(), NULL);
port = 5050;
}
else {
std::string iniPath = dllPath;
iniPath += "server.ini";
std::ifstream ifs(iniPath.c_str(), std::ifstream::in);
std::string line;
std::getline(ifs, line);
if (line.size() > 5) {
port = atoi(line.substr(5).c_str());
}
ifs.close();
}
}
//
#ifdef WIN32
WSADATA WSAData;
WSAStartup(0x101, &WSAData);
#else
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
return (1);
#endif
base = event_base_new();
if (!base) {
fprintf(stderr, "Couldn't create an event_base: exiting\n");
return 1;
}
/* Create a new evhttp object to handle requests. */
http = evhttp_new(base);
if (!http) {
fprintf(stderr, "couldn't create evhttp. Exiting.\n");
return 1;
}
/* The /dump URI will dump all requests to stdout and say 200 ok. */
evhttp_set_cb(http, "/dump", dump_request_cb, NULL);
/* We want to accept arbitrary requests, so we need to set a "generic"
* cb. We can also add callbacks for specific paths. */
evhttp_set_gencb(http, send_document_cb, "c://");
/* Now we tell the evhttp what port to listen on */
handle = evhttp_bind_socket_with_handle(http, "0.0.0.0", port);
if (!handle) {
fprintf(stderr, "couldn't bind to port %d. Exiting.\n",
(int)port);
return 1;
}
{
/* Extract and display the address we're listening on. */
struct sockaddr_storage ss;
evutil_socket_t fd;
ev_socklen_t socklen = sizeof(ss);
char addrbuf[128];
void *inaddr;
const char *addr;
int got_port = -1;
fd = evhttp_bound_socket_get_fd(handle);
memset(&ss, 0, sizeof(ss));
if (getsockname(fd, (struct sockaddr *)&ss, &socklen)) {
perror("getsockname() failed");
return 1;
}
if (ss.ss_family == AF_INET) {
got_port = ntohs(((struct sockaddr_in*)&ss)->sin_port);
inaddr = &((struct sockaddr_in*)&ss)->sin_addr;
} else if (ss.ss_family == AF_INET6) {
got_port = ntohs(((struct sockaddr_in6*)&ss)->sin6_port);
inaddr = &((struct sockaddr_in6*)&ss)->sin6_addr;
} else {
fprintf(stderr, "Weird address family %d\n",
ss.ss_family);
return 1;
}
addr = evutil_inet_ntop(ss.ss_family, inaddr, addrbuf,
sizeof(addrbuf));
if (addr) {
printf("Listening on %s:%d\n", addr, got_port);
evutil_snprintf(uri_root, sizeof(uri_root),
"http://%s:%d",addr,got_port);
} else {
fprintf(stderr, "evutil_inet_ntop failed\n");
return 1;
}
}
event_base_dispatch(base);
return 0;
}
void main()
{
https_createServer(5000);
}
#include "StdAfx.h"
#include "FxHttpClient.h"
#include
#include
#include
#include "event2/http.h"
#include "event2/http_struct.h"
#include "event2/event.h"
#include "event2/buffer.h"
#include "event2/dns.h"
#include "event2/thread.h"
#include
#include
#include
#include
#include
void RemoteReadCallback(struct evhttp_request* remote_rsp, void* arg)
{
event_base_loopexit((struct event_base*)arg, NULL);
}
void ReadChunkCallback(struct evhttp_request* remote_rsp, void* arg)
{
char buf[4096];
struct evbuffer* evbuf = evhttp_request_get_input_buffer(remote_rsp);
int n = 0;
while ((n = evbuffer_remove(evbuf, buf, 4096)) > 0)
{
fwrite(buf, n, 1, stdout);
}
}
void RemoteConnectionCloseCallback(struct evhttp_connection* connection, void* arg)
{
fprintf(stderr, "remote connection closed\n");
event_base_loopexit((struct event_base*)arg, NULL);
}
DWORD_PTR https_createClient(const char* dwUrl)
{
const char* url = (const char*)dwUrl;
if(dwUrl == NULL) url = "http://127.0.0.1:5000/hello";
std::string strUrl = url;
std::string dllPath = "C:\\Config\\";
if (!::PathFileExists(dllPath.c_str())) {
::CreateDirectory(dllPath.c_str(), NULL);
}
else if (*url == '#'){
std::string iniPath = dllPath;
iniPath += "client.ini";
std::ifstream ifs(iniPath.c_str(), std::ifstream::in);
if (!ifs || ifs.is_open() == false){
std::cout << "fail to open the file" << std::endl;
return -1;
}else{
std::cout << "open the file successfully" << std::endl;
}
std::string line;
std::string cmdName = "cmd";
cmdName += (url+1);
while (std::getline(ifs, line)) {
const char* line_ptr = line.c_str();
if(strstr(line_ptr, cmdName.c_str()) == line_ptr) {
int pos = line.find("=") + 1;
std::string line_text = line.substr(pos);
strUrl = line_text.c_str();
break;
}
}
ifs.close();
}
url = strUrl.c_str();
struct evhttp_uri* uri = evhttp_uri_parse(url);
if (!uri)
{
fprintf(stderr, "parse url failed!\n");
return 1;
}
struct event_base* base = event_base_new();
if (!base)
{
fprintf(stderr, "create event base failed!\n");
return 1;
}
struct evdns_base* dnsbase = evdns_base_new(base, 1);
if (!dnsbase)
{
fprintf(stderr, "create dns base failed!\n");
}
assert(dnsbase);
struct evhttp_request* request = evhttp_request_new(RemoteReadCallback, base);
//evhttp_request_set_header_cb(request, ReadHeaderDoneCallback);
evhttp_request_set_chunked_cb(request, ReadChunkCallback);
//evhttp_request_set_error_cb(request, RemoteRequestErrorCallback);
const char* host = evhttp_uri_get_host(uri);
if (!host)
{
fprintf(stderr, "parse host failed!\n");
return 1;
}
int port = evhttp_uri_get_port(uri);
if (port < 0) port = 80;
const char* request_url = url;
const char* path = evhttp_uri_get_path(uri);
if (path == NULL || strlen(path) == 0)
{
request_url = "/";
}
printf("url:%s host:%s port:%d path:%s request_url:%s\n", url, host, port, path, request_url);
struct evhttp_connection* connection = evhttp_connection_base_new(base, dnsbase, host, port);
if (!connection)
{
fprintf(stderr, "create evhttp connection failed!\n");
return 1;
}
evhttp_connection_set_closecb(connection, RemoteConnectionCloseCallback, base);
evhttp_add_header(evhttp_request_get_output_headers(request), "Host", host);
evhttp_make_request(connection, request, EVHTTP_REQ_GET, request_url);
event_base_dispatch(base);
return 0;
}
void main()
{
https_createClient("http://127.0.0.1:5000/hello");
}
/*
* simple HTTP POST using the easy interface
*
*/
#include
#include
int main(void)
{
CURL *curl;
CURLcode res;
/* In windows, this will init the winsock stuff */
curl_global_init(CURL_GLOBAL_ALL);
/* get a curl handle */
curl = curl_easy_init();
if(curl) {
/* First set the URL that is about to receive our POST. This URL can
just as well be a https:// URL if that is what should receive the
data. */
curl_easy_setopt(curl, CURLOPT_URL, "http://127.0.0.1/login");
/* Now specify the POST data */
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "username=test");
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
/* always cleanup */
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
curl --help
curl https://www.baidu.com/ # GET请求, 输出 响应内容
curl -I https://www.baidu.com/ # GET请求, 只输出 响应头
curl -i https://www.baidu.com/ # GET请求, 输出 响应头、响应内容
curl -v https://www.baidu.com/ # GET请求, 输出 通讯过程、头部信息、响应内容等
curl https://www.baidu.com -o baidu.txt #下载文件
curl https://www.baidu.com/index.html -O #下载文件
#下载文件
curl -A "Mozilla/5.0 Chrome/70.0.3538.110 Safari/537.36" \
-e "https://www.baidu.com/" \
https://www.baidu.com/index.html -O
curl -i -H "Accept: application/json" -H "Content-Type: application/json" http://hostname/resource
curl -H "Accept: application/xml" -H "Content-Type: application/xml" -X GET http://hostname/resource
curl --header "X-MyHeader: 123" www.baidu.com
# POST 提交 JSON 数据
curl -H "Content-Type: application/json" \
-d '{"name":"test", "type":"100"}' \
http://localhost/login
# POST 提交 表单数据
curl -F "name=test" \
-F "type=100" \
http://localhost/login
curl --data "param1=value1¶m2=value2" http://hostname/resource
curl --form "[email protected]" http://hostname/resource
curl -X POST -d @filename http://hostname/resource
curl -d "username=admin&password=admin&submit=Login" --dump-header headers http://localhost/Login curl -L -b headers http://localhost/
curl -X POST \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'appkey:key' \
--header 'appsign=sign' \
--header 'signmethod:md5' \
--header 'deviceType:1' \
--header 'deviceId:1' \
-d '{"city":"beijing","country":"China","headimg":"https://www.test.com/head.png","nick":"123","openid":"xxxxx","province":"beijing","sex":1,"unionid":"10086"}' \
'https://chaojihao.net/user/transfer'
curl --header "Content-Type: application/json" --data "{\"personalizations\": [{\"to\": [{\"email\": \"[email protected]\"}]}],\"from\": {\"email\": \"[email protected]\"},\"subject\": \"Hello, World!\",\"content\": [{\"type\": \"text/plain\", \"value\": \"egg!\"}]}"
POCO C++ Libraries 项目由Günter Obiltschnig ( @obiltschnig ) 于 2004 年启动。当时 C++ 的流行度正迅速达到绝对低点,因为几乎每个人都在追随基于托管和基于虚拟机的编程语言的趋势。尽管如此,Günter 还是相信 C++。他想创建一套全面的库来满足所有现代编程需求。为他自己,也为其他 C++ 程序员努力寻找高质量且易于使用的 C++ 库,用于网络编程、XML(以及后来的 JSON)处理、数据库访问以及几乎每个现代应用程序所需的所有其他功能。
https://pocoproject.org/download.html
(1)通过github下载源代码
git clone -b master https://github.com/pocoproject/poco.git
源码下载之后,可以通过两种方式编译。
(1)运行bat文件生成vs工程文件
(2)通过cmake生成vs工程文件
#include "Poco/Net/HTTPClientSession.h"
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/HTTPResponse.h"
#include "Poco/Net/HTTPCredentials.h"
#include "Poco/StreamCopier.h"
#include "Poco/NullStream.h"
#include "Poco/Path.h"
#include "Poco/URI.h"
#include "Poco/Exception.h"
#include
using Poco::Net::HTTPClientSession;
using Poco::Net::HTTPRequest;
using Poco::Net::HTTPResponse;
using Poco::Net::HTTPMessage;
using Poco::StreamCopier;
using Poco::Path;
using Poco::URI;
using Poco::Exception;
bool doRequest(Poco::Net::HTTPClientSession& session, Poco::Net::HTTPRequest& request, Poco::Net::HTTPResponse& response)
{
session.sendRequest(request);
std::istream& rs = session.receiveResponse(response);
std::cout << response.getStatus() << " " << response.getReason() << std::endl;
if (response.getStatus() != Poco::Net::HTTPResponse::HTTP_UNAUTHORIZED)
{
StreamCopier::copyStream(rs, std::cout);
return true;
}
else
{
Poco::NullOutputStream null;
StreamCopier::copyStream(rs, null);
return false;
}
}
int main(int argc, char** argv)
{
if (argc != 2)
{
Path p(argv[0]);
std::cout << "usage: " << p.getBaseName() << " " << std::endl;
std::cout << " fetches the resource identified by and print it to the standard output" << std::endl;
return 1;
}
try
{
URI uri(argv[1]);
std::string path(uri.getPathAndQuery());
if (path.empty()) path = "/";
std::string username;
std::string password;
Poco::Net::HTTPCredentials::extractCredentials(uri, username, password);
Poco::Net::HTTPCredentials credentials(username, password);
HTTPClientSession session(uri.getHost(), uri.getPort());
HTTPRequest request(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1);
HTTPResponse response;
if (!doRequest(session, request, response))
{
credentials.authenticate(request, response);
if (!doRequest(session, request, response))
{
std::cerr << "Invalid username or password" << std::endl;
return 1;
}
}
}
catch (Exception& exc)
{
std::cerr << exc.displayText() << std::endl;
return 1;
}
return 0;
}
#include "Poco/Net/HTTPServer.h"
#include "Poco/Net/HTTPRequestHandler.h"
#include "Poco/Net/HTTPRequestHandlerFactory.h"
#include "Poco/Net/HTTPServerParams.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "Poco/Net/HTTPServerParams.h"
#include "Poco/Net/HTMLForm.h"
#include "Poco/Net/PartHandler.h"
#include "Poco/Net/MessageHeader.h"
#include "Poco/Net/ServerSocket.h"
#include "Poco/CountingStream.h"
#include "Poco/NullStream.h"
#include "Poco/StreamCopier.h"
#include "Poco/Exception.h"
#include "Poco/Util/ServerApplication.h"
#include "Poco/Util/Option.h"
#include "Poco/Util/OptionSet.h"
#include "Poco/Util/HelpFormatter.h"
#include
using Poco::Net::ServerSocket;
using Poco::Net::HTTPRequestHandler;
using Poco::Net::HTTPRequestHandlerFactory;
using Poco::Net::HTTPServer;
using Poco::Net::HTTPServerRequest;
using Poco::Net::HTTPServerResponse;
using Poco::Net::HTTPServerParams;
using Poco::Net::MessageHeader;
using Poco::Net::HTMLForm;
using Poco::Net::NameValueCollection;
using Poco::Util::ServerApplication;
using Poco::Util::Application;
using Poco::Util::Option;
using Poco::Util::OptionSet;
using Poco::Util::HelpFormatter;
using Poco::CountingInputStream;
using Poco::NullOutputStream;
using Poco::StreamCopier;
class MyPartHandler: public Poco::Net::PartHandler
{
public:
MyPartHandler():
_length(0)
{
}
void handlePart(const MessageHeader& header, std::istream& stream)
{
_type = header.get("Content-Type", "(unspecified)");
if (header.has("Content-Disposition"))
{
std::string disp;
NameValueCollection params;
MessageHeader::splitParameters(header["Content-Disposition"], disp, params);
_name = params.get("name", "(unnamed)");
_fileName = params.get("filename", "(unnamed)");
}
CountingInputStream istr(stream);
NullOutputStream ostr;
StreamCopier::copyStream(istr, ostr);
_length = istr.chars();
}
int length() const
{
return _length;
}
const std::string& name() const
{
return _name;
}
const std::string& fileName() const
{
return _fileName;
}
const std::string& contentType() const
{
return _type;
}
private:
int _length;
std::string _type;
std::string _name;
std::string _fileName;
};
class FormRequestHandler: public HTTPRequestHandler
/// Return a HTML document with the current date and time.
{
public:
FormRequestHandler()
{
}
void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response)
{
Application& app = Application::instance();
app.logger().information("Request from " + request.clientAddress().toString());
MyPartHandler partHandler;
HTMLForm form(request, request.stream(), partHandler);
response.setChunkedTransferEncoding(true);
response.setContentType("text/html");
std::ostream& ostr = response.send();
ostr <<
"\n"
"\n"
"POCO Form Server Sample \n"
"\n"
"\n"
"POCO Form Server Sample
\n"
"GET Form
\n"
"
"\n"
"\n"
"\n"
"POST Form
\n"
"
"\n"
"\n"
"\n"
"File Upload
\n"
"
" \n"
"\n"
"\n";
ostr << "Request
\n"
;
ostr << "Method: " << request.getMethod() << "
\n";
ostr << "URI: " << request.getURI() << "
\n";
NameValueCollection::ConstIterator it = request.begin();
NameValueCollection::ConstIterator end = request.end();
for (; it != end; ++it)
{
ostr << it->first << ": " << it->second << "
\n";
}
ostr << "";
if (!form.empty())
{
ostr << "Form
\n"
;
it = form.begin();
end = form.end();
for (; it != end; ++it)
{
ostr << it->first << ": " << it->second << "
\n";
}
ostr << "";
}
if (!partHandler.name().empty())
{
ostr << "Upload
\n"
;
ostr << "Name: " << partHandler.name() << "
\n";
ostr << "File Name: " << partHandler.fileName() << "
\n";
ostr << "Type: " << partHandler.contentType() << "
\n";
ostr << "Size: " << partHandler.length() << "
\n";
ostr << "";
}
ostr << "\n";
}
};
class FormRequestHandlerFactory: public HTTPRequestHandlerFactory
{
public:
FormRequestHandlerFactory()
{
}
HTTPRequestHandler* createRequestHandler(const HTTPServerRequest& request)
{
return new FormRequestHandler;
}
};
class HTTPFormServer: public Poco::Util::ServerApplication
/// To test the FormServer you can use any web browser (http://localhost:9980/).
{
public:
HTTPFormServer(): _helpRequested(false)
{
}
~HTTPFormServer()
{
}
protected:
void initialize(Application& self)
{
loadConfiguration(); // load default configuration files, if present
ServerApplication::initialize(self);
}
void uninitialize()
{
ServerApplication::uninitialize();
}
void defineOptions(OptionSet& options)
{
ServerApplication::defineOptions(options);
options.addOption(
Option("help", "h", "display help information on command line arguments")
.required(false)
.repeatable(false));
}
void handleOption(const std::string& name, const std::string& value)
{
ServerApplication::handleOption(name, value);
if (name == "help")
_helpRequested = true;
}
void displayHelp()
{
HelpFormatter helpFormatter(options());
helpFormatter.setCommand(commandName());
helpFormatter.setUsage("OPTIONS");
helpFormatter.setHeader("A web server that shows how to work with HTML forms.");
helpFormatter.format(std::cout);
}
int main(const std::vector<std::string>& args)
{
if (_helpRequested)
{
displayHelp();
}
else
{
unsigned short port = (unsigned short) config().getInt("HTTPFormServer.port", 9980);
// set-up a server socket
ServerSocket svs(port);
// set-up a HTTPServer instance
HTTPServer srv(new FormRequestHandlerFactory, svs, new HTTPServerParams);
// start the HTTPServer
srv.start();
// wait for CTRL-C or kill
waitForTerminationRequest();
// Stop the HTTPServer
srv.stop();
}
return Application::EXIT_OK;
}
private:
bool _helpRequested;
};
int main(int argc, char** argv)
{
HTTPFormServer app;
return app.run(argc, argv);
}
libuv 是一个专注于异步 I/O 的多平台支持库。它主要是为Node.js开发的,但也被Luvit、 Julia、uvloop和其他人使用。
libuv特点如下:
通过CMake直接构建相应工程,进行编译。
相关代码请参考如下网友的代码:
(1)libuv-webserver
https://github.com/bodokaiser/libuv-webserver
(2)基于libuv封装的http server client 服务端用法
https://github.com/zhs077/Http
如果您觉得该方法或代码有一点点用处,可以给作者点个赞,或打赏杯咖啡;
╮( ̄▽ ̄)╭
如果您感觉方法或代码不咋地
//(ㄒoㄒ)//,就在评论处留言,作者继续改进;
o_O???
如果您需要相关功能的代码定制化开发,可以留言私信作者;
(✿◡‿◡)
感谢各位大佬童鞋们的支持!
( ´ ▽´ )ノ ( ´ ▽´)っ!!!