Boost.Asio基础(四)
来源:互联网 发布:广电机顶盒破解网络 编辑:程序博客网 时间:2024/05/16 10:36
TCP vs UDP vs ICMP
如前所述,对于所有类型的socket,并不是都有同样的成员函数。下面的表格列出了3个socket中存在的成员函数:
杂项函数
还有其他的一些函数用户处理连接或者输入/输出:
- local_endpoint():返回socket的本地连接地址。
- remote_endpoint():返回socket连接到的远程地址。
- native_handle():返回原始socket的句柄。只在你确实需要不经过Boost.Asio来操作原始socket时使用。
- non_blocking():返回socket是否是非阻塞的。
- native_non_blocking():同non_blocking()一样的函数,但是这个是在你用native_handle()获取原始句柄之后,还想查询是否非阻塞时使用。
- at_mark():返回true,当socket读取关于OOB数据的时候。极少用。
其他注意事项
最后需要注意的是,socket是不能复制的,它的复制构造函数是不可访问的:
ip::tcp::socket s1(service), s2(serviec);s1 = s2; //编译错误ip::socket::socket s3(s1); //编译错误
这样可以避免很多麻烦的问题,加入允许复制,那么会出现,两个socket持有一个相同的原始socket,那么到底谁对资源负责呢,谁在合适的时候释放它呢,很麻烦。所以Boost.Asio不允许复制socket。假如你真要复制socket,直接使用智能指针就行了:
typedef boost::shared_ptr<ip::tcp::socket> socket_ptr;socket_ptr sock1(new ip::tcp::socket(service));socket_ptr sock2(sock1);socket_ptr sock3;sock3 = sock1; // 这是可以的
Socket缓冲区
当向socket读取和写入数据的时候,你需要使用到缓冲区,它负责保存输入和输出的数据。缓冲区中内存的生存期要比I/O操作要长;你必须要保证,在I/O操作最终完成之前,这部分内存不会被释放掉。
这对同步操作来说,是很容易的。毫无疑问,缓冲区的生存期要比receive和send的要长:
char buff[512];...sock.receive(buffer(buff));strcpy(buff, "ok\n");sock.send(buffer(buff));
但对于异步操作来说,就不是那么简单了,下面是示例代码:
//非常不好的代码void on_read(const boost::system::error_code& err, std::size_t read_bytes){...}void func(){ char buff[512]; sock.async_receive(buffer(buff), on_read);}
在调用async_receive之后,buff就脱离了作用域,这部分内存就被释放掉了。也就是说我们把需要的数据拷贝到了我们不在拥有的内存上去了,这部分内存很可能被释放,然后重新分配给其他一些代码使用,毫无疑问,内存腐烂了。
有多种方法可以解决上面的问题:
- 使用全局缓冲区
- 创建缓冲区,并在操作完成后销毁
- 用一个连接对象来持有socket,以及socket的额外的数据,比如buffer(s)
第一个解决方法并不好,我们都知道全局变量是很不好的编码习惯。
第二种方法,我们使用智能指针,当操作完成后,缓冲区能够自动删除:
struct shared_buffer{ boost::shared_array<char> buff; int size; shared_buffer(size_t size) : buff(new char[size]), size(size) { } mutable_buffers_1 asio_buff() const { return buffer(buff.get(), size); }};//当脱离了on_read的作用域之后,async_receive也返回了,shared_buffer就被自动销毁了void on_read(shared_buffer, const boost::system::error_code& err, std::size_t read_bytes){}...shared_buffer buff(512);sock.async_receive(buff.asio_buff(), boost::bind(on_read, buff, _1, _2));
第三种方法,就是用一个单独的对象来管理socket和socket相关的数据,比如buffers对象。这是比较好的解决方案,但是稍显复杂,本章的最后来讨论此方法。
0 0
- Boost.Asio基础(四)
- Boost.Asio基础(一)
- Boost.Asio基础(二)
- Boost.Asio基础(三)
- Boost-asio之四
- Boost.Asio基础剖析
- Boost.Asio介绍--之四
- 翻译:Boost.Asio基础剖析
- boost::asio::steady_timer基础使用
- Boost.Asio(二)
- boost-ASIO--(1)
- boost-ASIO--(2)
- [Boost.asio] 深入linux网络编程(四):使用asio搭建商用服务器
- Boost.Asio基础(五) 异步编程初探
- Boost.Asio的基本剖析(Basic Boost.Asio Anatomy)
- Boost.Asio翻译(一)
- Boost.Asio翻译(二)
- boost asio学习(1)
- Python 的 Socket 编程教程
- (五)java运算
- 使用 libevent 和 libev 提高网络应用性能——I/O模型演进变化史
- 读书笔记
- 蓝桥杯 制作表格 循环条件判断
- Boost.Asio基础(四)
- HDU 1429 胜利大逃亡(续)(状压bfs)
- UVA - 10023 Square root
- 解决:windows安装程序无法将windows配置为在此计算机的硬件上运行
- objective-c block 详解
- facebook pop 学习笔记
- Initializing Spring root WebApplicationContext
- TRANSACTION_SOURCE_ID 跟 TRANSACTION_SOURCE_TYPE_ID所关联的表的关系
- gt9xx.c和gt9xx.h文件分析