列表来展示各个方法分别属于哪个socket类。
注意所有的异步方法都立刻返回,而它们相对的同步实现需要操作完成之后才能返回
1. 连接相关的函数
这些方法是用来连接或绑定socket、断开socket字连接以及查询连接是活动还是非活动的:
assign(protocol,socket):这个函数分配了一个原生的socket给这个socket实例。当处理老(旧)程序时会使用它(也就是说,原生socket已经被建立了)
open(protocol):这个函数用给定的IP协议(v4或者v6)打开一个socket。你主要在UDP/ICMPsocket,或者服务端socket上使用。
bind(endpoint):这个函数绑定到一个地址
connect(endpoint):这个函数用同步的方式连接到一个地址
async_connect(endpoint):这个函数用异步的方式连接到一个地址
is_open():如果套接字已经打开,这个函数返回true
close():这个函数用来关闭套接字。调用时这个套接字上任何的异步操作都会被立即关闭,同时返回error::operation_aborted错误码。
shutdown(type_of_shutdown):这个函数立即使send或者receive操作失效,或者两者都失效。
cancel():这个函数取消套接字上所有的异步操作。这个套接字上任何的异步操作都会立即结束,然后返回error::operation_aborted错误码。
eg:
io_service service;
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[1024];
sock.read_some(buffer(buff, 1024));
sock.shutdown(ip::tcp::socket::shutdown_receive);
sock.close();
2. 读写函数
这些是在socket上执行I/O操作的函数
对于异步函数来说,处理程序的格式void handler(const boost::system::error_code& e, size_t bytes)都是一样的
async_receive(buffer, [flags,] handler):这个函数启动从套接字异步接收数据的操作。
async_read_some(buffer,handler):这个函数和async_receive(buffer, handler)功能一样。
async_receive_from(buffer, endpoint[, flags], handler):这个函数启动从一个指定端点异步接收数据的操作。
async_send(buffer [, flags], handler):这个函数启动了一个异步发送缓冲区数据的功能。
async_write_some(buffer, handler):这个函数和async_send(buffer, handler)功能一致。
async_send_to(buffer, endpoint, handler):这个函数启动了一个异步send缓冲区数据到指定端点的功能。
receive(buffer [, flags]):这个函数异步地从所给的缓冲区读取数据。在读完所有数据或者错误出现之前,这个函数都是阻塞的。
read_some(buffer):这个函数的功能和receive(buffer)是一致的。
receive_from(buffer, endpoint [, flags])*:这个函数异步地从一个指定的端点获取数据并写入到给定的缓冲区。在读完所有数据或者错误出现之前,这个函数都是阻塞的。
send(buffer [, flags]):这个函数同步地发送缓冲区的数据。在所有数据发送成功或者出现错误之前,这个函数都是阻塞的。
write_some(buffer):这个函数和send(buffer)的功能一致。
send_to(buffer, endpoint [, flags]):这个函数同步地把缓冲区数据发送到一个指定的端点。在所有数据发送成功或者出现错误之前,这个函数都是阻塞的。
available():这个函数返回有多少字节的数据可以无阻塞地进行同步读取。
稍后我们将讨论缓冲区。让我们先来了解一下标记。标记的默认值是0,但是也可以是以下几种:
ip::socket_type::socket::message_peek:这个标记只监测并返回某个消息,但是下一次读消息的调用会重新读取这个消息。
ip::socket_type::socket::message_out_of_band:这个标记处理带外(OOB)数据,OOB数据是被标记为比正常数据更重要的数据。
ip::socket_type::socket::message_do_not_route:这个标记指定数据不使用路由表来发送。
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) );
下例是如何同步或异步地从不同类型的套接字读取数据的例子
eg1:对一个TCP套接字进行同步的读写
io_service service;
ip::tcp::endpoint ep( ip::address::from_string("127.0.0.1"), 80);
ip::tcp::socket sock(service);
sock.connect(ep);
sock.write_some(buffer("GET /index.html\r\n"));
std::cout << "bytes available " << sock.available() << std::endl;
char buff[512];
size_t read = sock.read_some(buffer(buff));
eg2:对一个UDP套接字进行同步的读写:
ip::udp::socket sock(service);
sock.open(ip::udp::v4());
ip::udp::endpoint receiver_ep("87.248.112.181", 80);
sock.send_to(buffer("testing\n"), receiver_ep);
char buff[512];
ip::udp::endpoint sender_ep;
sock.receive_from(buffer(buff), sender_ep);
注意:使用receive_from从一个UDP套接字读取时,需要一个默认构造的端点
eg3:从一个UDP服务器套接字中异步读取数据
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();
}
3. 套接字控制
这些函数用来处理套接字的高级选项
get_io_service():这个函数返回构造函数中传入的io_service实例
get_option(option):这个函数返回一个套接字的属性
set_option(option):这个函数设置一个套接字的属性
io_control(cmd):这个函数在套接字上执行一个I/O指令
这些是你可以获取/设置的套接字选项:
每个名字达标了一个内部套接字typedef或者类,下面是对它们的使用
ip::tcp::endpoint ep( ip::address::from_string("127.0.0.1"), 80);
ip::tcp::socket sock(service);
sock.connect(ep);
// TCP套接字可以重用地址
ip::tcp::socket::reuse_address ra(true);
sock.set_option(ra);
// 获取套接字读取的数据
ip::tcp::socket::receive_buffer_size rbs;
sock.get_option(rbs);
std::cout << rbs.value() << std::endl;
// 把套接字的缓冲区大小设置为8192
ip::tcp::socket::send_buffer_size sbs(8192);
sock.set_option(sbs);
注意:在上述特性工作之前,套接字要被打开。否则,会抛出异常
4. TCP VS UDP VS ICMP
不是所有的成员方法在所有的套接字类中都可用。我做了一个包含成员函数不同点的列表。如果一个成员函数没有出现在这,说明它在所有的套接字类都是可用的。
5. 其他方法
其他与连接和I/O无关的函数如下:
local_endpoint():这个方法返回套接字本地连接的地址。
remote_endpoint():这个方法返回套接字连接到的远程地址。
native_handle():这个方法返回原始套接字的处理程序。你只有在调用一个Boost.Asio不支持的原始方法时才需要用到它。
non_blocking():如果套接字是非阻塞的,这个方法返回true,否则false。
native_non_blocking():如果套接字是非阻塞的,这个方法返回true,否则返回false。但是,它是基于原生的套接字来调用本地的api。所以通常来说,你不需要调用这个方法(non_blocking()已经缓存了这个结果);你只有在直接调用native_handle()这个方法的时候才需要用到这个方法。
at_mark():如果套接字要读的是一段OOB数据,这个方法返回true。这个方法你很少会用到。
6. 其他考虑
套接字实例不能被拷贝,因为拷贝构造方法和=操作符是不可访问的。
ip::tcp::socket s1(service), s2(service);
s1 = s2; // 编译时报错
ip::tcp::socket s3(s1); // 编译时报错
这是非常有意义的,因为每一个实例都拥有并管理着一个资源(原生套接字本身)。如果我们允许拷贝构造,结果是我们会有两个实例拥有同样的原生套接字;这样我们就需要去处理所有者的问题(让一个实例拥有所有权?或者使用引用计数?还是其他的方法)Boost.Asio选择不允许拷贝(如果你想要创建一个备份,请使用共享指针)
typedef boost::shared_ptr<ip::tcp::socket> socket_ptr;
socket_ptr sock1(new ip::tcp::socket(service));
socket_ptr sock2(sock1); // ok
socket_ptr sock3;
sock3 = sock1; // ok

1771

被折叠的 条评论
为什么被折叠?



