Boost.Asio基础(二)

套接字 Sockets

Boost.Asio有三种类型的Socket类:ip::tcp,ip::udp和ip::icmp,三者都是可扩展的。你可以创建自己的Socket类,虽然做起来稍微复杂了点。假如你真的要这么做,可以参考boost/asio/ip/tcp.hpp,boost/asio/ip/udp.hpp和boost/asio/ip/icmp.hpp。它们都是很小的类,在内部使用typedef关键字。

你可以把ip::tcp,ip::udp和ip::icmp类,作为一个占位符;可以用下面的形式来访问类的和类的方法:

  • ip::tcp::socket, ip::tcp::acceptor, ip::tcp::endpoint, ip::tcp::resolver, ip::tcp::iostream
  • ip::udp::socket, ip::udp::endpoint, ip::udp::resolver
  • ip::icmp::socket, ip::icmp::endpoint, ip::icmp::resolver

相应的socket类创建一个对应的套接字。在io_service实例构造的时候,你需要传入这个socket:

io_service service;
ip::udp::socket sock(service);
sock.set_option(ip::udp::socket::reuse_address(true));

每一个socket的名字都由typedef而来:

  • ip::tcp::socket = basic_stream_socket
  • ip::udp::socket = basic_stream_socket
  • ip::icmp::socket = basic_stream_socket

同步错误代码(Synchronous error codes)

所有的同步函数都有例外情况,它们会抛出异常或者返回一个错误代码,例如下列代码:

sync_func(arg1, arg2 ... argN); //抛出异常
boost::system::error_code ec;
sync_func(arg1 arg2, ... , argN, ec); //返回错误代码

在后面,会遇到很多同步函数。为了保持简洁,后面会忽略返回错误代码的例外情况。

Socket成员函数

这些函数被分为几个组。并不是每个种类的socket都能访问所有这些成员函数。本节的最后,会有一张表列出哪些成员是隶属于何种socket类。

需要注意的是,所有的异步函数都是立即返回的,而同步版本的函数,只在操作完成之后才返回。

连接相关的类

有些函数用于连接或者绑定socket,断开连接,查询连接是否有效:

  • assign(protocol, socket):它给socket实例赋予原始套接字(原生)。使用它来处理一些遗留系统(这些系统中套接字通常是已经创建过了的)。
  • open(protocol):用给定的IP协议(v4或者v6)打开一个socket。主要用于UDP/ICMP socket,或者是用于服务器端socket。
  • bind(endpoint):绑定到指定的地址。
  • connect(endpoint):同步连接到指定的地址。
  • async_connect(endpoint):异步地连接到指定的地址。
  • is_open():socket是否是打开的。
  • close():关闭套接字。任何在此socket的异步操作都会被取消掉,并以error::operation_aborted错误代码完成。
  • shutdown(type_of_shutdown):禁用send,receive操作。
  • cancel():取消socket上的所有异步操作。所有在此socket上的异步操作都会被立即完成,并以error::operation_aborted错误代码返回。

    下面是例子:

ip::tcp::endpoint ep(ip::address::from_string("127.0.0.1"), 80);
ip::tcp::socket sock(service);
sock.open(ip::tcp::v4());
sock.connect(ep);
sock.write_some(buffer("GET /index.html\r\n"));
char buff[1204];
sock.read_some(buffer(buff, 1024));
sock.shutdown(ip::tcp::socket::shutdown_receive);
sock.close();

读/写函数

读写函数在socket上进行I/O操作。

对于异步函数,handler是一个回调函数,形如void handler(const boost::system::error_code& e, size_t bytes)。

  • async_receive(buffer, [flags], handler):在socket上开始异步的recevie操作。
  • async_read_some(buffer, handler):和async_receive作用相同。
  • async_receive_from(buffer, endpoint [,flags], handler:在指定的endpoint上开始异步的receive操作。
  • async_send(buffer [, flags], handler):将缓冲区中的数据异步的发送出去。
  • async_write_some(buffer, handler):和async_send相同。
  • async_send_to(buffer, endpoint, handler):在指定的endpoint上开始异步的发送操作。
  • receive(buffer [, flags]):同步接受数据到buffer,将阻塞,知道数据接收完成,或者出错。
  • read_some(buffer):和receive相同。
  • receive_from(buffer, endpoint [, flags]):从给定的endpoint接收数据,将阻塞,知道数据接收完成,或者出错。
  • send(buffer [, flags]):同步的发送缓冲区中的数据,将阻塞,知道数据发送完成,或者出错。
  • write_some(buffer):和send相同。
  • send_to(buffer, endpoint [, flags]):同步地将数据发送给指定endpoint。将阻塞,知道数据发送完成,或者出错。
  • available():返回在不阻塞的情况下,可以从socket中读取出多少字节。

这里简单讨论下缓冲区。默认的flags参数是0,也可以混合下面的值:

  • ip::socket_type::socket::message_peek:这个flag表示,只在缓冲区中检索数据。它可以返回消息,但是下一次读时,会重新读取这条数据。
  • ip::socket_type::socket::message_out_of_band:这个标志表示处理带外数据(OBB)。OBB数据比普通的数据更重要。对OBB数据的讨论超出了本书的范围。
  • ip::socket_type::socket::message_end_of_record:Windows下不支持。

大多数时候我们都使用message_peek,例子如下:

char buff[1024];
sock.receive(buffer(buff), ip::tcp::socket::message_peek);
memset(buff, 1024, 0);
//重新读取上次读取过的数据
sock.receive(buffer(buff));

下面的例子演示了同步和异步的区别:

  • 例子1,在tcp socket上同步的写和读:
ip::tcp::endpoint ep(ip::address::from_string("127.0.0.1", 80);
ip::tcp::socke sock(service);
sock.connect(ep);
sock.write_some(buffer("GET /index.html\r\n");
std::cout<< "有效字节数: "<< sock.available() <<std::endl;
char buff[512];
size_t read = sock.read_some(buffer(buff));
  • 例子2,在UDP socket上异步读和写:
ip::udp::socket sock(service);
sock.open(ip::udp::v4());
ip::udp::endpoint receiver_ep("xxx.xxx.xxx.xxx", 80);
sock.send_to(buffer("testing\n"), receiver_ep);
char buff[512];
ip::udp::endpoint sender_ep;
sock.receive_from(buffer(buff), sender_ep);
  • 例子3,从UDP服务器socket中异步读取:
using namespace boost::asio;
io_service service;
ip::udp::socket sock(service);
boost::asio::ip::udp::endpoint sender_ep;
char buff[512];

void on_read(const boost::system::error_code& err, std::size_t read_bytes)
{
    std::cout<<"read "<< read_bytes << std::endl;
    sock.async_receive_from(buffer(buff), sender_ep, on_read);
}

int main(int argc, char** argv)
{
    ip::udp::endpoint ep(ip::address::from_string("127.0.0.1"), 8001);
    sock.open(ep.protocol());
    sock.set_option(boost::asio::ip::udp::socket::reuse_address(true));
    sock.bind(ep);
    sock.async_receive_from(buffer(buff, 512), sender_ep, on_read);
    service.run();
    return 0;
}
时间: 2024-10-11 12:17:08

Boost.Asio基础(二)的相关文章

Boost.Asio基础(一)

Boost.Asio基础 Network API Boost.Asio 命名空间 boost::asio命名空间包含了Boost Asio库的所有东西,它下面还有一些子命名空间: boost::asio: 它包含了核心的类和功能模块.最重要的类是io_service和streambuf.里面还有一些自由函数,read,read_at,read_util,write等,以及它们的异步的版本. boost::asio::ip: 重要的类有address,endpoint,tcp,udp,icmp和自

Boost.Asio基础(五) 异步编程初探

异步编程 本节深入讨论异步编程将遇到的若干问题.建议多次阅读,以便吃透这一节的内容,这一节是对整个boost.asio来说是非常重要的. 为什么需要异步 如前所述,通常同步编程要比异步编程更简单.同步编程下,我们很容易线性地对问题进行考量,函数A调用完,继续执行B,B执行完,继续执行C,以此类推,相对比较直观.而对于异步编程,假设有5个事件,我们很难知道它们具体的执行顺序,你甚至不知道,它到底会不会被执行. 虽然编写异步的程序,很难,但是依然需要使用这种方法.因为服务器程序需要同时并行的处理大量

Boost.Asio基础(四)

TCP vs UDP vs ICMP 如前所述,对于所有类型的socket,并不是都有同样的成员函数.下面的表格列出了3个socket中存在的成员函数: 名称 TCP UDP ICMP async_read_some Yes - - async_receive_from - Yes Yes async_write_some Yes - - async_send_to - Yes Yes read_some Yes - - receive_rom - Yes Yes write_some Yes

Boost.Asio基础(三)

Socket控制 下面的函数进行处理一些高级的socket选项: get_io_service():返回io_service实例 get_option(option):返回socket option对象 set_option(option):设置socket 选项 io_control(cmd):在socket上执行I/O命令 以下是可以读取和设置的socket选项: 名称 描述 类型 broadcast 为真,允许广播消息 bool debug 为真,启用socket级别的调试 bool do

Boost.Asio基础

http://www.voidcn.com/article/p-exkmmuyn-po.html http://www.voidcn.com/article/p-xnxiwkrf-po.html http://www.voidcn.com/article/p-otlhzoos-po.html http://www.voidcn.com/article/p-dikksata-po.html http://www.voidcn.com/article/p-bwmizazs-po.html 原文地址:

boost::asio async_write也不能保证一次发完所有数据 二

只有看boost源码才能弄明白发生了什么.首先我是将vector里面写入了数据,然后用boost::asio::buffer将vector构造成了mutable_buffer_1对象. 参考该文档的重载形式:http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/reference/buffer/overload24.html [cpp] view plaincopyprint? buffer (24 of 28 overloads) C

boost.asio包装类st_asio_wrapper开发教程(2013.12.8更新)(二)

如果你是偶然浏览到这里,请先看 源代码及例程下载地址:命令行:svn checkout http://st-asio-wrapper.googlecode.com/svn/trunk/ st-asio-wrapper-read-only如果从svn客户端界面上打开,则只输入http://st-asio-wrapper.googlecode.com/svn/trunk/到地址栏即可git:https://github.com/youngwolf-project/st_asio_wrapper/,另

boost.asio源码剖析(二) ---- 架构浅析

* 架构浅析 先来看一下asio的0层的组件图.                     (图1.0) io_object是I/O对象的集合,其中包含大家所熟悉的socket.deadline_timer等对象,主要功能是提供接口给用户使用. services服务是逻辑功能的实现者,其中包含提供定时功能的deadline_timer_service.提供socket相关功能的win_iocp_socket_service(windows平台)/reactive_socket_service(其他

boost asio 学习(七) 网络基础 连接器和接收器(TCP示例)

http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting- started-with-boostasio?pg=8 7. Networking basics: connectors and acceptors (TCP)我们来学习boost的TCP网络编程.之前的篇章已经介绍了网络系统框架.我们只需要学习网络API函数即可 我们首先学习如何同步的连接主机.我们的代码作为客户端运行,使用tcp::socket对象.tcp::s