boost:asio网络库初学之echo服务器客户端实现

为什么想起来学网络库呢

前一阵在网上看到这么一段话

select 实在是太慢了.

>

在这种背景下, IBM 老大哥带领着MS老弟先搞了 IOCP . 然而开源的人有开源的做法, 在 NIH 综合症的影响下, BSD 的人敢为天下所不齿,
发明了 Kqueue. 同样在 NIH 综合症影响下, Linux 的一群 M* 的猴子捣鼓出了 epoll.

>

分裂, 让人头疼.

>

于是程序员们急需一个上天入地无所不能的法宝的法宝, 把这3家法宝给统御起来。

实在太符合我的心情了,我就很需要这样一个法宝,让自己舒服一点。因为是macos系统,类Unix,在服务器开发方面,linux有的基本都有,差不多是一致的,但
就是没有Epoll!!!,这就有些麻烦了,上一次写网关服务器时候,开发过程是这样的:
用sublime远程连接云服务器,
再用终端ssh运行调试,
就这样循环往复,再加上还没有补全,适应了xcode的舒服,所以痛苦ing。

说重点,为什么选择asio呢

1.asio属于boost的一部分,有可能被加入c++标准库,其代码质量稳定性及可靠性已不言而喻。
2.还是c++的原因,其源码使用了大多c++11特性,想在对其源码的学习过程中,对自己的c++知识进行一次加深和巩固
3.其主要针对于异步Proactor模式,而此模式相比较Reactor模式,学习难度稍高,所以想借着学习库使用的同时,能对其源码进行学习,提高事件驱动编程的
能力。
4.当然是跨平台了。

代码

客户端

//
//  main.cpp
//  AsioClient
//
//  Created by shiyi on 2016/12/10.
//  Copyright © 2016年 shiyi. All rights reserved.
//

#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>

using namespace boost;

int main(int argc, const char * argv[]) {

    asio::io_service service;//创建调度器
    asio::ip::tcp::socket sock(service);//创建socket
    asio::ip::tcp::endpoint ep(asio::ip::address::from_string("127.0.0.1"), 6666);//创建目标地址对象
    //异步连接
    sock.async_connect(ep, [](const boost::system::error_code &error){
        if(error)
        {
            std::cout << error.message() << std::endl;
            return;
        }
        std::cout << "connect succeed" << std::endl;
    });

    //如果不进行run调用的话,程序会直接结束,所以这里会等待async_connect结束,
    //因此上面connect同步还是异步其实是一样的
    service.run();

    char data[512];
    boost::system::error_code ec;
    size_t len;

    while(true)
    {
        std::cin >> data;

        //发送 如果不传入 ec(error_code)参数,则出错时会抛出异常,此时可以用try-catch进行捕获,如果也没捕获,程序会直接终止
        len = sock.write_some(asio::buffer(data), ec);
        if(ec)
        {
            std::cout << boost::system::system_error(ec).what() << std::endl;
            break;
        }

        //接收
        len = sock.read_some(asio::buffer(data), ec);
        if(ec)
        {
            std::cout << boost::system::system_error(ec).what() << std::endl;
            break;
        }

        std::cout << data << std::endl;

    }

    return 0;
}

服务端

//
//  main.cpp
//  AsioServer
//
//  Created by shiyi on 2016/12/10.
//  Copyright © 2016年 shiyi. All rights reserved.
//

#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>

using namespace boost;

using socket_ptr = boost::shared_ptr<asio::ip::tcp::socket>;//包装socket类型的智能指针

void client_session(socket_ptr sock)
{

    auto ep = sock->local_endpoint();
    std::cout<<ep.address().to_string()<<"连接"<<std::endl;

    char data[512];
    boost::system::error_code ec;
    size_t len;

    while(true)
    {
        len = sock->read_some(asio::buffer(data), ec);
        if(ec)
        {
            std::cout << boost::system::system_error(ec).what() << std::endl;
            break;
        }

        len = sock->write_some(asio::buffer(data), ec);
        if(ec)
        {
            std::cout << boost::system::system_error(ec).what() << std::endl;
            break;
        }
    }

    std::cout<<ep.address().to_string()<<"关闭"<<std::endl;

}

int main(int argc, const char * argv[]) {

    asio::io_service service;//创建调度器
    asio::ip::tcp::endpoint ep(asio::ip::address::from_string("127.0.0.1"), 6666);
    asio::ip::tcp::acceptor apt(service, ep);//创建连接器

    while(true)
    {
        socket_ptr sock(new asio::ip::tcp::socket(service));
        apt.accept(*sock);//接收新的连接
        boost::thread(boost::bind(client_session, sock));//开辟线程去处理该连接上的事务
    }

}

运行结果

客户端

这里写图片描述

服务端

这里写图片描述

请赐予我钱进的动力吧~
0%