使用boost::asio开发网络服务器

来源:互联网 发布:地外文明知乎 编辑:程序博客网 时间:2024/05/02 00:57

作为简单的示例,说明, 此服务器只是作为简单的数据收发示例,没有加入reactor模式的事件分法机制如select/epoll, 有待进一步完善。

因代码并非完全独自编写,所以注明是转载。


服务器端

#include <boost/asio.hpp>#include <boost/bind.hpp>#include <boost/shared_ptr.hpp>#include <boost/enable_shared_from_this.hpp>#include <iostream>using boost::asio::ip::tcp;#define max_len 1024class clientSession:public boost::enable_shared_from_this<clientSession>{public:clientSession(boost::asio::io_service& ioservice):m_socket(ioservice){memset(data_, '\0', sizeof(data_));}~clientSession(){}tcp::socket& socket(){return m_socket;}void start(){boost::asio::async_write(m_socket,boost::asio::buffer("link successed!"),boost::bind(&clientSession::handle_write, shared_from_this(),boost::asio::placeholders::error));/*async_read跟客户端一样,还是不能进入handle_read函数,如果你能找到问题所在,请告诉我,谢谢*/// --已经解决,boost::asio::async_read(...)读取的字节长度不能大于数据流的长度,否则就会进入// ioservice.run()线程等待,read后面的就不执行了。//boost::asio::async_read(m_socket,boost::asio::buffer(data_,max_len),//         boost::bind(&clientSession::handle_read,shared_from_this(),//         boost::asio::placeholders::error));//max_len可以换成较小的数字,就会发现async_read_some可以连续接收未收完的数据m_socket.async_read_some(boost::asio::buffer(data_, max_len),boost::bind(&clientSession::handle_read, shared_from_this(),boost::asio::placeholders::error));}private:void handle_write(const boost::system::error_code& error){if (error){m_socket.close();}}void handle_read(const boost::system::error_code& error){if (!error){std::cout << data_ << std::endl;//boost::asio::async_read(m_socket,boost::asio::buffer(data_,max_len),//     boost::bind(&clientSession::handle_read,shared_from_this(),//     boost::asio::placeholders::error));m_socket.async_read_some(boost::asio::buffer(data_, max_len),boost::bind(&clientSession::handle_read, shared_from_this(),boost::asio::placeholders::error));}else{m_socket.close();}}private:tcp::socket m_socket;char data_[max_len];};class serverApp{typedef boost::shared_ptr<clientSession> session_ptr;public:serverApp(boost::asio::io_service& ioservice, tcp::endpoint& endpoint):m_ioservice(ioservice),acceptor_(ioservice, endpoint){session_ptr new_session(new clientSession(ioservice));acceptor_.async_accept(new_session->socket(),boost::bind(&serverApp::handle_accept, this, boost::asio::placeholders::error,new_session));}~serverApp(){}private:void handle_accept(const boost::system::error_code& error, session_ptr& session){if (!error){std::cout << "get a new client!" << std::endl;//实现对每个客户端的数据处理session->start();//在这就应该看出为什么要封session类了吧,每一个session就是一个客户端session_ptr new_session(new clientSession(m_ioservice));acceptor_.async_accept(new_session->socket(),boost::bind(&serverApp::handle_accept, this, boost::asio::placeholders::error,new_session));}}private:boost::asio::io_service& m_ioservice;tcp::acceptor acceptor_;};int main(int argc, char* argv[]){boost::asio::io_service myIoService;short port = 8100/*argv[1]*/;//我们用的是inet4tcp::endpoint endPoint(tcp::v4(), port);//终端(可以看作sockaddr_in)完成后,就要accept了serverApp sa(myIoService, endPoint);//数据收发逻辑myIoService.run();return 0;}



客户端

#include <boost/asio.hpp>#include <boost/bind.hpp>#include <boost/shared_ptr.hpp>#include <iostream>using boost::asio::ip::tcp;class client{public:client(boost::asio::io_service& io_service, tcp::endpoint& endpoint): socket(io_service)//这里就把socket实例化了{//连接服务端 connectsocket.async_connect(endpoint,boost::bind(&client::handle_connect, this, boost::asio::placeholders::error));memset(getBuffer, '\0', 1024);}~client(){}private:void handle_connect(const boost::system::error_code& error){if (!error){//一连上,就向服务端发送信息boost::asio::async_write(socket, boost::asio::buffer("hello, server!"),boost::bind(&client::handle_write, this, boost::asio::placeholders::error));/**读取服务端发下来的信息*这里很奇怪,用async_read根本就不能进入handle_read函数**/// --已经解决,boost::asio::async_read(...)读取的字节长度不能大于数据流的长度,否则就会进入// ioservice.run()线程等待,read后面的就不执行了。//boost::asio::async_read(socket,//     boost::asio::buffer(getBuffer,1024),//     boost::bind(&client::handle_read,this,boost::asio::placeholders::error)//    );socket.async_read_some(boost::asio::buffer(getBuffer, 1024),boost::bind(&client::handle_read, this, boost::asio::placeholders::error));}else{socket.close();}}void handle_read(const boost::system::error_code& error){if (!error){std::cout <<"getBuffer"<< std::endl;//boost::asio::async_read(socket,//         boost::asio::buffer(getBuffer,1024),//         boost::bind(&client::handle_read,this,boost::asio::placeholders::error)//        );//这样就可以实现循环读取了,相当于while(1)//当然,到了这里,做过网络的朋友就应该相当熟悉了,一些逻辑就可以自行扩展了//想做聊天室的朋友可以用多线程来实现socket.async_read_some(boost::asio::buffer(getBuffer, 1024),boost::bind(&client::handle_read, this, boost::asio::placeholders::error));}else{socket.close();}}void handle_write(const boost::system::error_code& error){}private:tcp::socket socket;char getBuffer[1024];};int main(int argc, char* argv[]){//if(argc != 3)//{// std::cerr << “Usage: chat_client <host> <port>\n”;//    return 1;//}//我觉IO_SERVICE是一个基本性的接口,基本上通常用到的类实例都需要通过它来构造//功能我们可以看似socketboost::asio::io_service io_service;//这个终端就是服务器//它的定义就可以看作时sockaddr_in,我们用它来定义IP和PORTtcp::endpoint endpoint(boost::asio::ip::address_v4::from_string("127.0.0.1"/*argv[1]*/), 8100/*argv[2]*/);//既然socket和sockaddr_in已经定义好了,那么,就可以CONNECT了//之所以为了要把连接和数据处理封成一个类,就是为了方便管理数据,这点在服务端就会有明显的感觉了boost::shared_ptr<client> client_ptr(new client(io_service, endpoint));//执行收发数据的函数io_service.run();return 0;}



0 0
原创粉丝点击