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

来源:互联网 发布:wamp配置php环境变量 编辑:程序博客网 时间:2024/05/02 02:35

为什么想起来学网络库呢

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

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 0