20120530--asio让网络编程代码变简洁了

  前面说到要使用asio库,需要编译datetime等库。现在使用asio库的时候,发现以前使用C语言实现一个简单的服务器模型时,代码是多么的冗长,想放到几个函数里面呢,觉得关系又比较密切,阅读不方便;放到一起吧又觉得代码太长。对asio库不了解,今天看了网上一个实现echo服务器的代码,很简洁。整个代码从建立服务器,到分发客户端数据,几行代码搞定。当然,首次接触asio和boost的人,对这段代码要理解清楚会费点神的。其中的bind的使用shared_ptr的使用,以及对asio机制的了解等。如果要理解这么短的代码实现原理,那肯定不是一天两天能够好的。至少需要去熟悉下boost里面的那么几个库吧。

   曾经的我,作为一个服务的编程人员,只是那时是数据库开发;现在的我,作为一个客户端开发人员。对服务器建设这块都有很强的探索心里。一个强大的服务器是如何建立起来的,是如何实现业务分离的;如何面对大数据访问,安全问题如何解决等等。

  一直知道公司的服务器是java做的,开始还以为公司可能这个数据比较小吧,但是前几天知道公司的在线交易服务系统也是JAVA程序员在维护着。刚好,这段时间一直想搞asio,就发现了LF领导者跟随者模式,半同步半异步模式什么的。还像还看到了这些模式的java调用接口,而是使用C++封装成中间件给JAVA调用。于是,我想。是不是做java服务端的人更容易熟悉服务器架构,因为他们每天都和这个东西打交道,出现问题没办法最后只能进入C++层找,OK,最后成为一个服务器C++高手,哈哈。

  而就我身边的每一个C++开发者而言,都很希望能够做服务端开发,可似乎不如人意。换了几个工作,最后还是搞客户端。就其原因应该就是我们都希望自己找个公司去学习服务端开发,但一个招服务端开发的公司,对这个经验要求都比较高,与其招一个新手来慢慢摸索,不如公司内部其他语言的转来做更适合。毕竟,现在服务器大多数开发语言都是java活C#。

既然这样,那俺们就自己来搭建自己的服务器吧,从asio开始,一步一步的来。今天就把网上找的asio的HelloWorld程序贴上来吧.

服务器端的:

//下面是一个异步模式的简单的Tcp echo服务器
#include <iostream>
#include <string>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/smart_ptr.hpp>

using namespace boost::asio;
using boost::system::error_code;
using ip::tcp;

struct CHelloWorld_Service
{
    //类的初始化创建:设置io_service, 设置1000端口
    CHelloWorld_Service(io_service &iosev)
         :m_iosev(iosev),m_acceptor(iosev, tcp::endpoint(tcp::v4(), 1000))
    {
    }
    
    //创建一个tcp的socket;且还是侦听
    void start()
    {
        // 开始等待连接(非阻塞)
         boost::shared_ptr<tcp::socket> psocket(new tcp::socket(m_iosev));

        // 触发的事件只有error_code参数,所以用boost::bind把socket绑定进去
         m_acceptor.async_accept(*psocket, boost::bind(&CHelloWorld_Service::accept_handler, this, psocket, _1) );
     }

    // 有客户端连接时accept_handler触发
    void accept_handler(boost::shared_ptr<tcp::socket> psocket, error_code ec)
     {
        if(ec) return;

        // 继续等待连接
         start();

        // 显示远程IP
         std::cout << psocket->remote_endpoint().address() << std::endl;

        // 发送信息(非阻塞)
         boost::shared_ptr<std::string> pstr(new std::string("hello async world!"));
         psocket->async_write_some(buffer(*pstr),
             boost::bind(&CHelloWorld_Service::write_handler, this, pstr, _1, _2));
     }

    // 异步写操作完成后write_handler触发
    void write_handler(boost::shared_ptr<std::string> pstr, error_code ec, size_t bytes_transferred)
     {
        if(ec)
             std::cout<< "发送失败!" << std::endl;
        else
             std::cout<< *pstr << " 已发送" << std::endl;
     }

private:
     io_service &m_iosev;
     ip::tcp::acceptor m_acceptor;
};


int main(int argc, char* argv[])
{
     //建立io服务器
     io_service iosev;

     CHelloWorld_Service sev(iosev);

    //开始侦听socket的连接;和开始接收远程数据
     sev.start();

     //开始执行回调函数
     iosev.run();

    return 0;
}

客户端的:

#include <iostream>
#include <boost/asio.hpp>
 
using namespace boost::asio; 
int main(int argc, char* argv[])
{
    // 所有asio类都需要io_service对象
    io_service iosev;
    // socket对象
    ip::tcp::socket socket(iosev);
    // 连接端点,这里使用了本机连接,可以修改IP地址测试远程连接
    ip::tcp::endpoint ep(ip::address_v4::from_string("127.0.0.1"), 1000);
    // 连接服务器
    boost::system::error_code ec;
    socket.connect(ep,ec);
    // 如果出错,打印出错信息
    if(ec)
    {
        std::cout << boost::system::system_error(ec).what() << std::endl;
        return -1;
    }
    // 接收数据
    char buf[100];
    size_t len=socket.read_some(buffer(buf), ec);
    std::cout.write(buf, len);
 
    return 0;
}

学习这东西,我一般推荐先抄袭的。不会不要急,要去看别人怎么做的,先会用。要用好当然要了解底层实现。当需要过程的,一个东西,不知道用它来做什么,就去看它是怎么实现的没意思。先盗版、然后才能给出自己的正版。哈哈!

 如上面的这个服务器和客户端类,我们就需要去了解一些东西了:

 io_service &m_iosev;//这里的io_service是何方神圣
 ip::tcp::acceptor m_acceptor;//这里的ip::tcp::acceptor又为何物
如果看到这个代码的人没有接触过boost,那就更要为bind的使用而感到惊奇。

哎,真实学还无涯啊


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值