diff --git a/READEM.txt b/READEM.txt new file mode 100644 index 0000000..dc45249 --- /dev/null +++ b/READEM.txt @@ -0,0 +1,21 @@ +# boost asio Server framework +# 使用boost asio简单封装的服务器框架 +# +# 仅供学习和参考,任何偏离此意向的改动和使用与作者无关 +# +# 目录src中为服务器源码 +# 目录client中为简易测试客户端源码 +# 代码依赖于boost库,在进行编译前请确保已安装boost,作者在boost-1.55中进行开发和简单测试 +# 代码支持windows和linux平台,windows请自行新建工程并配置头文件路径和库文件路径 +# +# 在已安装boost的情况下: +1.修改Makefile中 + 16行 INCLUDES 路径 + 19行 LIBS路径 为相应boost的库文件和头文件路径 + +2.执行make,即可在当前目录生成Server文件 + +3.服务启动的地址和端口在main.cpp写死,编译前请自行修改为相应的地址和端口 + + +ps:欢迎大家吐槽和交流,本人CSDN:fly2010love \ No newline at end of file diff --git a/client/Client b/client/Client new file mode 100644 index 0000000..e3410b5 Binary files /dev/null and b/client/Client differ diff --git a/client/Makefile b/client/Makefile new file mode 100644 index 0000000..25b6554 --- /dev/null +++ b/client/Makefile @@ -0,0 +1,31 @@ +#bash/bin + +TOPDIR=. + +TARGE=Client + +SRCS = $(wildcard *.cpp) +OBJS = $(SRCS:.cpp = .o) +CC = g++ + +#dirs := Kmp buf +#all: +# $(foreach N,$(dirs),$(make -C $(N))) + +#include header +INCLUDES = -I/home/boostlib/include + +#include lib path +LIBS = -L/home/boostlib/lib +LDLIBS = -lboost_system -lboost_thread -lpthread + +CCFLAGS = -g -Wall + +$(TARGE):$(OBJS) + $(CC) $^ -o $@ $(INCLUDES) $(LIBS) $(LDLIBS) $(CCFLAGS) + +%.o:%.cpp + $(CC) -c $< $(CCFLAGS) + +clean: + rm *.o $(TARGE) diff --git a/client/client.cpp b/client/client.cpp new file mode 100644 index 0000000..d0fd278 --- /dev/null +++ b/client/client.cpp @@ -0,0 +1,48 @@ +#include +#include +#include +#include + +using boost::asio::ip::tcp; + +enum { max_length = 1024 }; + +int main(int argc, char* argv[]) +{ + //try + { + boost::asio::io_service io_service; + + tcp::resolver resolver(io_service); + tcp::resolver::query query(tcp::v4(), "192.168.199.146", "12345"); + tcp::resolver::iterator iterator = resolver.resolve(query); + + while(1) + { + tcp::socket s(io_service); + boost::asio::connect(s, iterator); + boost::system::error_code gnoredErr; + s.shutdown(boost::asio::ip::tcp::socket::shutdown_both, gnoredErr); + } + + // using namespace std; // For strlen. + // std::cout << "Enter message: "; + // char request[max_length]; + // std::cin.getline(request, max_length); + // size_t request_length = strlen(request); + // boost::asio::write(s, boost::asio::buffer(request, request_length)); + + // char reply[max_length]; + // size_t reply_length = boost::asio::read(s, + // boost::asio::buffer(reply, request_length)); + // std::cout << "Reply is: "; + // std::cout.write(reply, reply_length); + // std::cout << "\n"; + } + //catch (std::exception& e) + { + //std::cerr << "Exception: " << e.what() << "\n"; + } + + return 0; +} \ No newline at end of file diff --git a/src/AsioPool.cpp b/src/AsioPool.cpp new file mode 100644 index 0000000..b297dba --- /dev/null +++ b/src/AsioPool.cpp @@ -0,0 +1,62 @@ +#include "AsioPool.h" + +#include +#include +#include + +AsioPool::AsioPool(int iPoolSize) +{ + m_ioIndex = 0; + if (iPoolSize <= 0) + { + iPoolSize = 1; + } + + for (int i=0; i threadPtr; + std::vector threads; + size_t i,j; + + for (i=0; ijoin(); + } +} + +void AsioPool::OnStop() +{ + size_t i; + for (i=0; istop(); + } +} + +boost::asio::io_service& AsioPool::GetIoService() +{ + boost::asio::io_service& service = *m_ioServicePtrs.at(m_ioIndex); + if (++m_ioIndex >= m_ioServicePtrs.size()) + { + m_ioIndex = 0; + } + return service; +} \ No newline at end of file diff --git a/src/AsioPool.h b/src/AsioPool.h new file mode 100644 index 0000000..0184bdb --- /dev/null +++ b/src/AsioPool.h @@ -0,0 +1,33 @@ +#ifndef ASIOPOOL_H_ +#define ASIOPOOL_H_ + +#include +#include +#include +#include + + +class AsioPool + :private boost::noncopyable +{ +public: + AsioPool(int iPoolSize); + + void OnRun(); + + void OnStop(); + + boost::asio::io_service& GetIoService(); +protected: + +private: + typedef boost::shared_ptr IOServicePtr; + typedef boost::shared_ptr IOWorkPtr; + + std::vector m_ioServicePtrs; + std::vector m_ioWorkPtrs; + + size_t m_ioIndex; +}; + +#endif//ASIOPOOL_H_ \ No newline at end of file diff --git a/src/Connection.cpp b/src/Connection.cpp new file mode 100644 index 0000000..6e0de07 --- /dev/null +++ b/src/Connection.cpp @@ -0,0 +1,141 @@ +#include +#include + +#include "Connection.h" + +Connection::Connection(boost::asio::io_service& ioservice, boost::asio::io_service& work_service, + RequestHandler& ReqHandler) + : m_socket(ioservice) + , m_work_service(work_service) + , m_work_strand(work_service) + , m_ReqHandler(ReqHandler) +{ + m_recvCacheBufPtr.reset(new std::vector); +} + +void Connection::OnStart() +{ + boost::system::error_code gnoredErr; + m_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, gnoredErr); + // m_socket.async_read_some(boost::asio::buffer(m_Buffers), + // boost::bind(&Connection::HandleRead, shared_from_this(), + // boost::asio::placeholders::error, + // boost::asio::placeholders::bytes_transferred)); + +} + +boost::asio::ip::tcp::socket& Connection::GetSocket() +{ + return m_socket; +} + + +void Connection::HandleRead(const boost::system::error_code& errCode, std::size_t bytes_transferred) +{ + if (!errCode) + { + int iret = 0; + //m_ReqHandler,处理请求,比如登录等等 + if (!iret) + { + std::string timeStr; + GetCurrentStringTime(timeStr); + + std::cout<resize(m_recvCacheBufPtr->size() + bytes_transferred); + std::copy(m_Buffers.begin(), m_Buffers.begin() + bytes_transferred, + (m_recvCacheBufPtr->begin() + m_recvCacheBufPtr->size()));*/ + + std::string reply = "Wirte";//回复OK + + boost::asio::async_write(m_socket, boost::asio::buffer(reply), + boost::bind(&Connection::HandleWirte, shared_from_this(), + boost::asio::placeholders::error)); + //m_work_strand.post(boost::bind(&Connection::HandleReadDone + // , shared_from_this(), errCode)); + + // boost::asio::streambuf request; + // std::ostream request_stream(&request); + // request_stream << "Accept: */*\r\n"; + // request_stream << "Connection: close\r\n\r\n"; + + // Send the request. + //boost::asio::write(m_socket, request); + + } + else if (-1 == iret) + { + m_socket.async_read_some(boost::asio::buffer(m_Buffers), + boost::bind(&Connection::HandleRead, shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + } + //else + //{ + // std::string reply;//回复失败 + // boost::asio::async_write(m_socket, boost::asio::buffer(reply), + // boost::bind(&Connection::HandleWirte, shared_from_this(), + // boost::asio::placeholders::error)); + //} + } + else + { + std::string timeStr; + GetCurrentStringTime(timeStr); + std::cout<begin(), m_recvCacheBufPtr->end()); + std::cout< +#include +#include +#include +#include +#include "RequestHandler.h" + +#include +#include +#include + +#include +#include +#include + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include +#include + +#define ACCESS _access +#define MKDIR(a) _mkdir((a)) +#define SLEEP(n) Sleep(1000*n) + + +#else +#include +#include +#include +#include +#include + +#define ACCESS access +#define MKDIR(a) mkdir((a),0766) +#define SLEEP(n) sleep(n) + +#endif + +using namespace std; + + +class Connection + :public boost::enable_shared_from_this + ,private boost::noncopyable +{ +public: + Connection(boost::asio::io_service& ioservice, boost::asio::io_service& work_service, RequestHandler& ReqHandler); + + void OnStart(); + + boost::asio::ip::tcp::socket& GetSocket(); + +protected: + void HandleRead(const boost::system::error_code& errCode, std::size_t bytes_transferred); + void HandleReadDone(const boost::system::error_code& errCode); + + void HandleWirte(const boost::system::error_code& errCode); + + time_t GetCurrentStringTime(std::string& timeStr, int iIndex=0) + { + std::string tmpStr; + char buf[32] = {0}; + +#ifdef _WIN32 + time_t t; + tm *tp; + t = time(NULL); + tp = localtime(&t); + sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d", + tp->tm_year+1900, tp->tm_mon+1, tp->tm_mday + ,tp->tm_hour, tp->tm_min, + (tp->tm_sec - iIndex > 0) ? tp->tm_sec - iIndex: 0); + + timeStr = buf; + return t - iIndex; +#else + time_t now; + time(&now); + now = now - iIndex; + struct tm timenow; + localtime_r(&now, &timenow); + strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &timenow); + timeStr = buf; + return now; +#endif + } +private: + + boost::asio::ip::tcp::socket m_socket; + boost::asio::io_service& m_work_service; + + boost::array m_Buffers; + + boost::shared_ptr > m_recvCacheBufPtr; + + boost::asio::strand m_work_strand; + + RequestHandler& m_ReqHandler; + +}; + +typedef boost::shared_ptr ConnectionPtr; + +#endif //CONNECTION_H_ \ No newline at end of file diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..915fcbb --- /dev/null +++ b/src/Makefile @@ -0,0 +1,31 @@ +#bash/bin + +TOPDIR=. + +TARGE=Server + +SRCS = $(wildcard *.cpp) +OBJS = $(SRCS:.cpp = .o) +CC = g++ + +#dirs := Kmp buf +#all: +# $(foreach N,$(dirs),$(make -C $(N))) + +#include header +INCLUDES = -I/home/boostlib/include + +#include lib path +LIBS = -L/home/boostlib/lib +LDLIBS = -lboost_system -lboost_thread -lpthread + +CCFLAGS = -g -Wall + +$(TARGE):$(OBJS) + $(CC) $^ -o $@ $(INCLUDES) $(LIBS) $(LDLIBS) $(CCFLAGS) + +%.o:%.cpp + $(CC) -c $< $(CCFLAGS) + +clean: + rm *.o $(TARGE) diff --git a/src/RequestHandler.cpp b/src/RequestHandler.cpp new file mode 100644 index 0000000..207c28c --- /dev/null +++ b/src/RequestHandler.cpp @@ -0,0 +1 @@ +#include "RequestHandler.h" \ No newline at end of file diff --git a/src/RequestHandler.h b/src/RequestHandler.h new file mode 100644 index 0000000..88bc77e --- /dev/null +++ b/src/RequestHandler.h @@ -0,0 +1,17 @@ +#ifndef REQUESTHEANDLER_H_ +#define REQUESTHEANDLER_H_ + +#include +#include +#include + +class RequestHandler + :boost::noncopyable +{ +public: + RequestHandler(){}; +protected: +private: +}; + +#endif //REQUESTHEANDLER_H_ \ No newline at end of file diff --git a/src/Server.cpp b/src/Server.cpp new file mode 100644 index 0000000..0a8a084 --- /dev/null +++ b/src/Server.cpp @@ -0,0 +1,98 @@ +#include "Server.h" +#include +#include +#include + +Server::Server(const std::string& address, const std::string& port, const int iPoolSize) + :m_io_AsioPool(iPoolSize) + , m_work_AsioPool(1) + ,m_acceptor(m_io_AsioPool.GetIoService()) + ,m_signalSet(m_work_AsioPool.GetIoService() ) +{ + m_signalSet.add(SIGINT); + m_signalSet.add(SIGTERM); + m_signalSet.async_wait(boost::bind(&Server::HandleStop, this)); + + boost::asio::ip::tcp::resolver resolver(m_acceptor.get_io_service()); + boost::asio::ip::tcp::resolver::query query(address, port); + boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query); + m_acceptor.open(endpoint.protocol()); + m_acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); + m_acceptor.bind(endpoint); + m_acceptor.listen(99999); + + OnAccept(); + +} + +void Server::OnRun() +{ + m_io_thread.reset(new boost::thread(boost::bind(&AsioPool::OnRun, &m_io_AsioPool))); + m_work_thread.reset(new boost::thread(boost::bind(&AsioPool::OnRun, &m_work_AsioPool))); +} + +void Server::OnAccept() +{ + m_connectionPtr.reset(new Connection(m_io_AsioPool.GetIoService(), m_work_AsioPool.GetIoService(), m_RequstHandler)); + + m_acceptor.async_accept(m_connectionPtr->GetSocket(), + boost::bind(&Server::HandleAccept, this, + boost::asio::placeholders::error) ); +} + +void Server::OnStop() +{ + m_io_AsioPool.OnStop(); + m_work_AsioPool.OnStop(); + + m_io_thread->join(); + m_work_thread->join(); +} + +time_t GetCurrentStringTime(std::string& timeStr, int iIndex=0) + { + std::string tmpStr; + char buf[32] = {0}; + +#ifdef _WIN32 + time_t t; + tm *tp; + t = time(NULL); + tp = localtime(&t); + sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d", + tp->tm_year+1900, tp->tm_mon+1, tp->tm_mday + ,tp->tm_hour, tp->tm_min, + (tp->tm_sec - iIndex > 0) ? tp->tm_sec - iIndex: 0); + + timeStr = buf; + return t - iIndex; +#else + time_t now; + time(&now); + now = now - iIndex; + struct tm timenow; + localtime_r(&now, &timenow); + strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &timenow); + timeStr = buf; + return now; +#endif + } + +void Server::HandleAccept(const boost::system::error_code& errCode) +{ + OnAccept(); + static int iCount = 0; + if (!errCode) + { + std::string timeStr; + GetCurrentStringTime(timeStr); + std::cout<iCount="<OnStart(); + } + +} + +void Server::HandleStop() +{ + OnStop(); +} diff --git a/src/Server.h b/src/Server.h new file mode 100644 index 0000000..1286fbb --- /dev/null +++ b/src/Server.h @@ -0,0 +1,49 @@ +#ifndef SERVER_H_ +#define SERVER_H_ + +#include +#include +#include +#include +#include +#include +#include "AsioPool.h" +#include "Connection.h" +#include "RequestHandler.h" + +class Server + :public boost::noncopyable +{ +public: + Server(const std::string& ip, const std::string& port, const int iPoolSize); + + void OnRun(); + + void OnAccept(); + + void OnStop(); + + void HandleAccept(const boost::system::error_code& errCode); + + void HandleStop(); + +protected: +private: + AsioPool m_io_AsioPool; + AsioPool m_work_AsioPool; + + boost::asio::ip::tcp::acceptor m_acceptor; + + boost::asio::signal_set m_signalSet; + + typedef boost::shared_ptr threadPtr; + threadPtr m_io_thread; + threadPtr m_work_thread; + + ConnectionPtr m_connectionPtr; + + RequestHandler m_RequstHandler; +}; + + +#endif //SERVER_H_ \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..c07b2e2 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,19 @@ +#include "Server.h" +#include + +int main(int argc, char**argv) +{ + try + { + Server ser("192.168.199.146", "12345", 32); + ser.OnRun(); + + getchar(); + } + catch (std::exception& e) + { + std::cout<<"Server Start Exception"<