我是Boost的新手。我正在开发一个小服务器。当客户端向我的服务器发送消息时,我遇到了问题。我的服务器调用函数读取套接字两次
这是我的客户端类中的代码
void ClientManager::ToRecv(void)
{
this->_socket.async_read_some(boost::asio::buffer(_buffer),
_strand.wrap(boost::bind(&ClientManager::HandleRead, this, boost::asio::placeholders::error))
);
}
void ClientManager::HandleRead(boost::system::error_code const & error)
{
_mutex.lock();
std::cout << boost::this_thread::get_id() << " client->HandleRead()" << std::endl;
for (unsigned int i = 0; i < _buffer.size(); ++i)
{
std::cout << _buffer[i]; // I display the message
}
std::cout << std::endl;
_mutex.unlock();
this->ToRecv();
}
当客户端连接时,我调用start函数。这是我启动服务器时在控制台中显示的内容:
我创建了3个帖子。
Server Connect
[004FE200] Thread Start
[004FE238] Thread Start
[004FE7C8] Thread Start
这是我将putty客户端连接到我的服务器
[004FE7C8] acceptor->NewClient()
[004FE7C8] client->Start()
这是我的服务器在客户端发送“hello world”时显示的内容。
[004FE238] client->HandleRead()
hello world
[004FE7C8] client->HandleRead()
llo world
答案 0 :(得分:1)
我不知道_buffer是什么类型的,但它应该看起来像这样,请注意bytes_transferred
。
void ClientManager::HandleRead(boost::system::error_code const & error, size_t bytes_transferred)
{
_mutex.lock();
std::cout << boost::this_thread::get_id() << " client->HandleRead()" << std::endl;
for (unsigned int i = 0; i < bytes_transferred; ++i)
{
std::cout << _buffer[i]; // I display the message
}
std::cout << std::endl;
_mutex.unlock();
this->ToRecv();
}
互斥锁有什么用?这是否有必要?
我会这样写:
void ClientManager::HandleRead(boost::system::error_code const & error, size_t bytes_transferred)
{
std::cout << boost::this_thread::get_id() << " client->HandleRead()" << std::endl;
std::copy(_buffer.begin(), _buffer.begin() + bytes_transferred, std::ostream_iterator<char>(std::cout));
std::cout << std::endl;
this->ToRecv();
}
现在,你可能会看到的(并且已经从下面的评论中看到)是HandleRead()
将被多次调用,只包含部分消息。如果在调用read
函数之前知道消息的大小,则可以使用组合函数async_read()。这是boost::asio
命名空间中的自由函数。
答案 1 :(得分:0)
我猜想你在某处初始化了_buffer
到“Hello World”。
调用socket::async_read_some
并不能保证在调用完成处理程序之前已读取所有数据。您可以使用asio
命名空间中的组合自由函数来执行此操作。
所以可能发生的事情是你在第一次调用处理程序时获得部分消息,其余部分在第二次调用中。但是,如果缓冲区已经初始化,那么看起来就像是你收到了两次消息。
更改此行以传递占位符以传输的字节数:
_strand.wrap(
boost::bind(
&ClientManager::HandleRead,
this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred)));
然后适当更改HandleRead()
功能:
void ClientManager::HandleRead(
boost::system::error_code const & error,
size_t bytes_transferred) // Add bytes_transferred
{
_mutex.lock();
std::cout << boost::this_thread::get_id() << " client->HandleRead()" << std::endl;
// Then -- check the buffer up to the number of bytes transferred:
for (unsigned int i = 0; i < bytes_transferred; ++i)
{
std::cout << _buffer[i]; // I display the message
}
std::cout << std::endl;
_mutex.unlock();
this->ToRecv();
}