boost.asio系列——socket编程

asio的主要用途还是用于socket编程,本文就以一个tcp的daytimer服务为例简单的演示一下如何实现同步和异步的tcp socket编程。

客户端

客户端的代码如下:

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

using boost::asio::ip::tcp;

int main(int argc, char* argv[])
    {
        try
        {
            boost::asio::io_service io_service;
            tcp::endpoint end_point(boost::asio::ip::address::from_string("127.0.0.1"), 3200);

tcp::socketsocket(io_service);
            socket.connect(end_point);

for (;;)
            {
                boost::array<char, 128> buf;
                boost::system::error_code error;

size_t len = socket.read_some(boost::asio::buffer(buf), error);

if (error == boost::asio::error::eof)
                    break; // Connection closed cleanly by peer.
                else if (error)
                    throw boost::system::system_error(error); // Some other error.

std::cout.write(buf.data(), len);
            }
        }
        catch (std::exception& e)
        {
            std::cerr << e.what() << std::endl;
        }

return 0;
    }

主要流程如下:

  1. 通过tcp::socket类定义一个tcp client对象socket
  2. 通过connect函数连接服务器,打开socket连接。
  3. 通过read_some函数来读数据

另外,还可以通过write_some来写数据,通过close来关闭socket连接(这里是通过释放socket对象隐式释放连接)。

服务器

服务器代码如下:

#include <ctime>
    #include <iostream>
    #include <string>
    #include <boost/asio.hpp>

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

int main()
    {
        try
        {
            asio::io_service io_service;
            tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 3200));

for (;;)
            {
                tcp::socket socket(io_service);
                acceptor.accept(socket);

time_t now = time(0);
                std::string message = ctime(&now);

system::error_code ignored_error;
                socket.write_some(asio::buffer(message), ignored_error);
            }
        }
        catch (std::exception& e)
        {
            std::cerr << e.what() << std::endl;
        }

return 0;
    }

主要流程如下:

  1. 通过tcp::acceptor类创建一个tcp server对象,并绑定端口(也可以不在构造器中自动绑定,而通过bind函数手动绑定)
  2. 通过accept函数获取远端连接
  3. 通过远端连接的write_some函数将数据发往客户端

异步服务器

前面的服务器是同步版本,在大并发的场景下一般需要用到异步socket。服务器的异步版本如下:

#include <ctime>
    #include <iostream>
    #include <string>
    #include <memory>
    #include <functional>
    #include <boost/asio.hpp>

using boost::asio::ip::tcp;
    using namespace std;

void process_client(shared_ptr<tcp::socket> client)
    {
        time_t now = time(0);
        shared_ptr<string> message(new string(ctime(&now)));

auto callback = [=](const boost::system::error_code& err ,size_t size)
        {
            if ((int)size == message->length())
                cout << "write completed" << endl;
        };

client->async_send(boost::asio::buffer(*message), callback);
    }

typedef function<void (const boost::system::error_code&)> accept_callback;
    void start_accept(tcp::acceptor& server)
    {
        shared_ptr<tcp::socket> client(new tcp::socket(server.get_io_service()));
        accept_callback callback = [&server, client](const boost::system::error_code& error)
            {
                if (!error)
                    process_client(client);

start_accept(server);
            };

server.async_accept(*client, callback);
    }

int main()
    {
        try
        {
            boost::asio::io_service io_service;
            tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 3200));
            start_accept(acceptor);
            io_service.run();
        }
        catch (std::exception& e)
        {
            std::cerr << e.what() << std::endl;
        }
        return 0;
    }

这个异步版本的逻辑倒不是很复杂,基本上和.net中传统的异步socket相似,不过需要注意的是,由于c++中内存需要自己管理,而asio框架也没有提供任何管理机制,因此需要注意async_accept、async_send等函数的参数生命周期,切记不能在里面传入栈变量的引用。如果是堆变量,需要确保释放,本例中我是通过share_ptr来实现的自动释放。

更多的示例请参看asio官方文档

boost.asio系列——socket编程

时间: 2024-10-13 16:17:49

boost.asio系列——socket编程的相关文章

boost.asio系列——buffer

创建buffer 在io操作中,对数据的读写大都是在一个缓冲区上进行的,在asio框架中,可以通过asio::buffer函数创建一个缓冲区来提供数据的读写.buffer函数本身并不申请内存,只是提供了一个对现有内存的封装. char d1[128];    size_t bytes_transferred = sock.receive(asio::buffer(d1)); 直接用字符串做buffer也是常见的形式: string str = " hello world " ;    

boost.asio系列——io_service

IO模型 io_service对象是asio框架中的调度器,所有异步io事件都是通过它来分发处理的(io对象的构造函数中都需要传入一个io_service对象). asio::io_service io_service;    asio::ip::tcp::socket socket(io_service); 在asio框架中,同步的io主要流程如下: 应用程序调用IO对象成员函数执行IO操作 IO对象向io_service 提出请求. io_service 调用操作系统的功能执行连接操作. 操

Boost.Asio c++ 网络编程翻译(20)

异步服务端 这个图表是相当复杂的:从Boost.Asio出来你可以看到4个箭头指向on_accept,on_read,on_write和on_check_ping.着也就意味着你永远不知道哪个异步调用是下一个完成的调用,但是你可以确定的是它是这4个操作中的一个. 现在,我们是异步的了:我们可以继续保持单线程.接受客户端连接是最简单的部分,如下所示: ip::tcp::acceptor acceptor(service, ip::tcp::endpoint(ip::tcp::v4(), 8001)

Boost.Asio c++ 网络编程翻译(1)

第一次翻译,希望大家多多指正 实战出精华 Boost.Asio C++ 网络编程 用具体的C++网络编程例子来提升你的技能 John Torjan 用具体的C++网络编程例子来提升你的技能 Copyright ? 2013 Packt Publishing 版权所有,除了在鉴定文章或者评论中进行简单引用,如果没有经过出版者事先的书面授权,该书的任何部分都不能被转载.存储在检索系统中.或者以任何形式和方式传阅. 在这本书准备发行之前,我们已经尽我们最大的努力去保证书中信息的准确性.但是,这本书中包

boost.asio系列——Timer

同步Timer asio中提供的timer名为deadline_timer,它提供了超时计时的功能.首先以一个最简单的同步Timer为例来演示如何使用它. #include <iostream>    #include <boost/asio.hpp> int main()    {        boost::asio::io_service io;        boost::asio::deadline_timer timer(io, boost::posix_time::s

Boost.Asio c++ 网络编程翻译(30)[完结]

PS:至此终于完成了Boost.Asio C++ network programming一书的翻译,这是我人生第一本完整翻译的书,从开始的磕磕绊绊,到最后小有心得,我收获很多.我将把这个系列的博客进行整理和校对,希望有兴趣的人可以帮我一起,来给大家提供更好更专业的阅读体验. 句柄追踪信息到文件 默认情况下,句柄的追踪信息被输出到标准错误流(相当于std::cerr).你想把输出重定向到其他地方的可能性是非常高的.对于控制台应用,输出和错误输出都被默认输出到相同的地方,也就是控制台.但是对于一个w

Boost.Asio c++ 网络编程翻译(4)

同步VS异步 首先,异步编程和同步编程是有极大的不同的.在同步编程中,你所有的操作都是顺序执行的,比如从一个socket中读取(请求),然后写入(回应)到socket中.每一个操作操作都是阻塞的.因为操作是阻塞的,所以为了不影响主程序,当读写一个socket时,通常创建一个或多个线程来处理socket的输入/输出.因此,同步的服务端/客户端通常是多线程的. 相反的,异步编程是事件驱动的.你启动了一个操作,但是你不知道它何时会结束:你只是提供一个回调,当操作结束时,它会调用这个API,并返回操作结

Boost.Asio c++ 网络编程翻译(14)

保持活动 假如,你需要做下面的操作: io_service service; ip::tcp::socket sock(service); char buff[512]; ... read(sock, buffer(buff)); 在这个例子中,sock和buff的存在时间都必须比read()调用的时间要长.也就是说,在调用read()返回之前,它们都必须有效.这就是你期望的:你传给一个方法的所有参数在参数内部都必须有效.当我们采用异步方式时,事情会变得越复杂. io_service servi

Boost.Asio c++ 网络编程翻译(28)

协程 Boost.Asio的作者在2009-2010年间实现了非常酷的一个部分,协程,它能让你更简单地设计你的异步应用. 它们可以让你同时享受同步和异步两个世界中最好的部分,这就是:异步编程但是很简单就能遵循流程控制,就好像应用是按流程实现的. 正常的流程已经在情形1种展示了,如果使用协程,你会尽可能的接近情形2. 简单来说,就是协程允许在一个方法中的指定位置存在入口来暂停和恢复运行. 如果你要使用协程,你需要只能在boost/libs/asio/example/http/server4目录下找