一般来说这个错误都是由于系统可用的非分页内存不够导致的。WSASend需要在非分页内存中锁定内存,如果失败,则返回这个错误。
有时候观察系统内存还有很多,但是依然发生了这个错误,多出现于虚拟机环境中。具体原因未知,但当时的确存在系统缓冲区不足的问题,例如ipconfig都无法显示完整信息。
为了避免或尽可能的减少此类错误的返回,程序上可以做一些调整,或者符合某些编码范式。
首 先注意不要调用WSASend发送一个巨大的数据包,多大才算巨大,这个取决于不同的环境,一般来说8192是一个上限。因为这个值正好为许多系统缺省的 socket buffer。如果需要发大包,那么最好是调用多次WSASend。其次最好不要同时调用多次异步WSASend,应该首先将数据包插入队列,然后在完成 了一次WSASend之后再检查队列,发送下一个。
- void do_async_send(T_SBUF buffer)
- {
- if(closed_ || !connected_) return on_async_send_fail(buffer);
-
- bool send = pending_buffers_.empty();
- pending_buffers_.push_back(buffer);
-
- if(send)
- {
- boost::asio::async_write(socket_,
- buffer,
- strand_.wrap(boost::bind(&tcp_client::handle_send,
- shared_from_this(),
- boost::asio::placeholders::error,buffer)));
- }
- }
- void handle_send(const boost::system::error_code& error,T_SBUF buffer)
- {
- if(closed_) return;
-
- _ASSERT(!pending_buffers_.empty());
- _ASSERT(buffer == pending_buffers_.front());
-
- if(error) return do_stop(error);
- if(pending_buffers_.empty()) {_ASSERT(false);return do_stop(error);}
- pending_buffers_.pop_front();
-
- if(!on_send(buffer))
- {
- graceful_close_ = true;
- return do_stop(boost::system::error_code());
- }
-
- if(!pending_buffers_.empty())
- {
- T_SBUF next_buffer = pending_buffers_.front();
- boost::asio::async_write(socket_,
- next_buffer,
- strand_.wrap(boost::bind(&tcp_client::handle_send,
- shared_from_this(),
- boost::asio::placeholders::error,next_buffer)));
- }
- }
(胡宇光) |