一、常见的开源网络库:
- Adaptive Communication Environment,简称ACE,自适应通信环境。ACE代码复杂,封装繁琐,框架比较笨重,难修改,默认使用select,并非epoll;
- ZeroMQ,简称ZMQ。轻量级,简洁且灵活;
- boost::asio,本文将实现一个使用asio的demo;
- libevent:基于epoll的异步处理机制的库,多数被用来进行网络编程;
- tinyserver:微型服务器,默认是单线程允许,所以实际的生成价值并不高;
- LibSourcey:是一个基于c++14标准,用于高性能网络服务器开发的,较冷门,参考资料少;
- Casablanca:基于C++11标准,C++ REST SDK的别名,微软开源的项目,基于REST API协议,集成了 boost::asio;
- websocket++:基于 boost库的一个封装,封装了asio。
上面的一些库并没有接触过,先在这里做个标记,以后有时间了慢慢的啃,接下来给出一个使用boost::asio进行网络通信的demo。
二、boost::asio简介:
在这里先简单的介绍一下这个库,在1.4.3版本引入epoll来实现异步处理,可以结合其他boost库来实现更为轻大的功能,十分的灵活,充分理解架构后,我们可以在其基础上进行自定义。
- 几个重要的类:
boost::asio::ip::tcp::socket(async_connect,async_accept)
boost::asio::io_service //封装IO操作
boost::asio::ip::tcp::acceptor
- code:
#include <iostream>
#include <string>
#include <unordered_map>
#include <csignal>
#include "server.h"
#include "log.h"
#include <boost/asio.hpp>
#include <boost/bind.hpp>
void accept_handler(const boost::system::error_code& _ec);
boost::asio::io_service ios;
unsigned short port;
boost::asio::ip::tcp::acceptor* pacceptor;
boost::asio::ip::tcp::socket _socket(ios);
std::string netbuffer;
void write_handler(const boost::system::error_code &ec, std::size_t bytes_transferred) {
_socket.close();
log("[Info]", "server complete");
pacceptor->async_accept(_socket, accept_handler);
}
void read_handler(const boost::system::error_code &ec, std::size_t bytes_transferred) {
log("[Info]", "recv:" + netbuffer);
std::string http_data = "HTTP/1.1 200 OK\r\nServer: loong\r\nContent-type: text/html\r\n\r\n" + netbuffer;
log("[Info]", http_data);
_socket.async_write_some(boost::asio::buffer(http_data), write_handler);
}
void accept_handler(const boost::system::error_code& _ec) {
if (_ec) {
log("[Error]", "server accept");
return;
}
log("[Info]", _socket.remote_endpoint().address().to_string());
_socket.async_read_some(boost::asio::buffer(netbuffer), read_handler);
}
void handler(int s) {
log("[Info]", "Server exit!");
if (pacceptor != NULL) {
boost::asio::ip::tcp::acceptor* tmp = pacceptor;
pacceptor = NULL;
delete tmp;
}
exit(0);
}
int main(int argc, char **argv) {
netbuffer.resize(4096);
if (argc != 3 || argv[1][0] != '-' || argv[1][1] != 'p') {
std::cout << "[Usage] " << argv[0] << " -p <port>" << std::endl;
return 0;
}
port = (unsigned short)strtol(argv[2], nullptr, 10);
daemonize();
signal(SIGINT, handler);
pid_t server_pid;
while ((server_pid = server_singleton()) != -1) {
kill(server_pid, SIGINT);
}
log("[Info]", "Server start!");
pacceptor = new boost::asio::ip::tcp::acceptor(ios, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port));
pacceptor->async_accept(_socket, accept_handler);
log("[Info]", "server start 1.");
ios.run();
log("[Info]", "server start 2.");
boost::asio::ip::tcp::acceptor* tmp = pacceptor;
pacceptor = NULL;
delete tmp;
return 0;
}
- log.h:
#ifndef LOONG_LOG_H
#define LOONG_LOG_H
#include <string>
#include <cstring>
#define HANDLE(X) \
do { \
if ((X) == -1) { \
log("[Error]", strerror(errno)); \
exit(1); \
} \
} while(0)
void log(const std::string &log_head, const std::string &log_body);
#endif //LOONG_LOG_H
- server.h
#ifndef LOONG_SERVER_H
#define LOONG_SERVER_H
#include <unistd.h>
void daemonize();
pid_t server_singleton();
#endif //LOONG_SERVER_H
剩下的以后有机会深入学习一下,最近看到公司的一些项目在用websocket,之前被公司的大佬实现了一些,需要我搞一点其他的东西,我想说,看别人的代码是真的不舒服…
就先这样吧,以后周末有时间了完善一下,深入一下。