socket成员方法

这些方法被分成了几组。并不是所有的方法都可以在各个类型的套接字里使用。这个部分的结尾将有一个
列表来展示各个方法分别属于哪个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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值