zoukankan      html  css  js  c++  java
  • Boost asio学习笔记之二—— 网络编程

    boost库中的网络编程的例子比较复杂,不太好理解,所以,从网上找了一个简单点的例子。网址如下:http://blog.chinaunix.net/u3/93184/showart_1846119.html.经过修改,可以运行。

    服务器代码:


    Servier.cpp

    #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 main(int argc , char* 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 main(int argc,char* 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("192.168.1.119"/*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;
    }

    修改192.168.1.119为127.0.0.1,然后先运行server,再运行client,一切ok.


  • 相关阅读:
    我的浏览器和常用扩展
    Win10安装.Net Framework4.7及更高版本
    压缩和解压工具bandizip
    Oracle trunc()函数的用法
    Oracle 中 decode 函数用法
    Js/Jquery获取iframe中的元素 在Iframe中获取父窗体的元素方法
    String literal is not properly closed by a double-quote eclipse
    linux 启动 Oracle 实例
    查询当前Oracle数据库的实例
    sqlplus 执行 sql 文件
  • 原文地址:https://www.cnblogs.com/lzjsky/p/2017198.html
Copyright © 2011-2022 走看看