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.


  • 相关阅读:
    _ 下划线 Underscores __init__
    Page not found (404) 不被Django的exception中间件捕捉 中间件
    从装修儿童房时的门锁说起
    欧拉定理 费马小定理的推广
    线性运算 非线性运算
    Optimistic concurrency control 死锁 悲观锁 乐观锁 自旋锁
    Avoiding Full Table Scans
    批量的单向的ssh 认证
    批量的单向的ssh 认证
    Corrupted MAC on input at /usr/local/perl/lib/site_perl/5.22.1/x86_64-linux/Net/SSH/Perl/Packet.pm l
  • 原文地址:https://www.cnblogs.com/lzjsky/p/2017198.html
Copyright © 2011-2022 走看看