支持HW团队,就支付宝领取下面的红包吧! (打开支付宝就能领取!er1OEj73Uj), (打开支付宝收索“516503473”), 你领取消费,HW有奖励。红包使用无条件限制,有条件请注意是不是有病毒。

Login or Sign up | Validate
| Search

博主:初学MPEG

初学MPEG 本博客-采用Python的web框架Django与Mysql数据库,致力于对Python、Django的了解 与研究
Django技术QQ群:XXXXXXX
Python技术QQ群:XXXXXXX

Category

Keywords

本站最新博文

友情链接  

[转]boost::asio::ip::tcp实现网络通信的小例子

类别:STL、Boost 状态:游客可见,可回,自己可关联(良好) 阅读:7660 评论:0 时间:April 12, 2012, 8:41 a.m.
关键字:boost asio

 来源:http://blog.chinaunix.net/space.php?uid=20864319&do=blog&id=448813

我稍稍整理了下,就是加了点注释,很基本的东西,大家可以参考socket的几个流程,我上面也有提示的,希望对大家有所帮助。最后,如果大家有什么好的方法希望能让我也分享下,谢谢!
服务端:

#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 1024
class 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 _tmain(int argc, _TCHAR* argv[])
{
        boost::asio::io_service myIoService;
        short port = 8100/*argv[1]*/;
        //我们用的是inet4

        tcp::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>
using boost::asio::ip::tcp;
class client
{
public:
        client(boost::asio::io_service& io_service,tcp::endpoint& endpoint)
                : socket(io_service)//这里就把socket实例化了
        {
                //连接服务端 connect
                socket.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 _tmain(int argc, _TCHAR* argv[])
{
        //if(argc != 3)
        //{
        // std::cerr << “Usage: chat_client <host> <port>\n”;
        //    return 1;
        //}
        //我觉IO_SERVICE是一个基本性的接口,基本上通常用到的类实例都需要通过它来构造
        //功能我们可以看似socket
        boost::asio::io_service io_service;
        //这个终端就是服务器
        //它的定义就可以看作时sockaddr_in,我们用它来定义IP和PORT
        tcp::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;
}

 

操作:

Please Login (or Sign Up) to leave a comment