套接字缓冲区 boost asio

当从一个套接字读写内容时,你需要一个缓冲区,用来保存读取和写入的数据。缓冲区内存的有效时间必须比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就已经超出有效范围,它的内存当然会被释放。当我们开始从套接字接收一些数据时,我们会把它们拷贝到一片已经不属于我们的内存中;它可能会被释放,或者被其他代码重新开辟来存入其他的数据,结果就是:内存冲突。

对于上面的问题有几个解决方案:

使用全局缓冲区

创建一个缓冲区,然后在操作结束时释放它

使用一个集合对象管理这些套接字和其他的数据,比如缓冲区数组

第一个方法显然不是很好,因为我们都知道全局变量非常不好。此外,如果两个实例使用同一个缓冲区怎么办?

下面是第二种方式的实现:

void on_read(char * ptr, const boost::system::error_code & err, std::size_t read_bytes)

 {

delete[] ptr;

}

....char * buff = new char[512];

sock.async_receive(buffer(buff, 512), boost::bind(on_read,buff,_1,_2));

或者,如果你想要缓冲区在操作结束后自动超出范围,使用共享指针

struct shared_buffer 

{boost::shared_array 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超出范围时, boost::bind对象被释放了

,// 同时也会释放共享指针

void on_read(shared_buffer, const boost::system::error_code & err, std::size_t read_bytes)

 {

}

sock.async_receive(buff.asio_buff(), boost::bind(on_read,buff,_1,_2));

shared_buffer类拥有实质的shared_array<>,shared_array<>存在的目的是用来保存shared_buffer实例的拷贝-当最后一个share_array<>元素超出范围时,shared_array<>就被自动销毁了,而这就是我们想要的结果。

因为Boost.Asio会给完成处理句柄保留一个拷贝,当操作完成时就会调用这个完成处理句柄,所以你的目的达到了。那个拷贝是一个boost::bind的仿函数,它拥有着实际的shared_buffer实例。这是非常优雅的!第三个选择是使用一个连接对象来管理套接字和其他数据,比如缓冲区,通常来说这是正确的解决方案但是非常复杂。在这一章的末尾我们会对这种方法进行讨论。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

金士顿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值