客户端向服务器发送大约165kB的数据。起初一切都很好。 但是当客户端再次发送相同的数据(165kB)时,我在服务器端收到一个断言。 Assert包含有关“迭代器越界”的信息
在调用堆栈上,有一些关于read_until
方法的信息。
所以我认为我犯了一个错误。
TCP异步服务器代码如下:
handle_read 的代码:
void Session::handle_read(const boost::system::error_code& a_error,
size_t a_nbytestransferred)
{
if (!a_error)
{
std::ostringstream dataToRetrive;
dataToRetrive << &m_bufferRead;
boost::thread threads(boost::bind(retriveMessageFromClient,
shared_from_this(), dataToRetrive.str()));
boost::asio::async_write(m_socket, m_bufferWrite,
boost::bind(&Session::handle_write,
shared_from_this(), boost::asio::placeholders::error));
}
else
disconnect();
}
handle_write 的代码:
void Session::handle_write(const boost::system::error_code& a_error)
{
if (!a_error)
{
boost::asio::async_read_until(m_socket,
m_bufferRead, boost::regex(G_strREQUESTEND),
boost::bind(&Session::handle_read, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
else
disconnect();
}
m_bufferRead,m_bufferWrite都是Session类的成员。
class Session...
boost::asio::streambuf m_bufferRead;
boost::asio::streambuf m_bufferWrite;
更新
我发现问题出现在我的代码的其他地方。 比线程完成任务后,metdhod 调用do_writeMessage()。
主题功能
void retriveMessageFromClient(boost::shared_ptr<Session>& A_spSesion, std::string A_strDataToRetrive)
{
try
{
std::string strAnswer;
bool bFind = (A_strDataToRetrive.find(G_REGEX_BIG_FILE_BEGIN) != std::string::npos);
if(bFind) // Write large data to osFile
{
A_strDataToRetrive = boost::regex_replace(A_strDataToRetrive, boost::regex(G_REGEX_BIG_FILE_BEGIN), std::string(""));
std::string strClientFolder = str(boost::format("%1%%2%") % CLIENT_PRE_FOLDER_FILE % A_spSesion->getIdentifier());
std::string strClientFile = str(boost::format("%1%\\%2%%3%") % strClientFolder % strClientFolder % CLIENT_EXTENSION);
if ( boost::filesystem::exists(strClientFolder) )
boost::filesystem::remove_all(strClientFolder);
else
boost::filesystem::create_directory( strClientFolder );
std::ofstream osFile(strClientFile.c_str());
osFile << A_strDataToRetrive;
osFile.close();
strAnswer = str(boost::format(G_FILE_WAS_WRITE) % strClientFile);
}
else
{
double dResult = sin (30.0 * 3.14/180);
strAnswer = str(boost::format(G_OPERATION_RESULT) % dResult);
}
// Sleep thread
boost::xtime timeToSleep;
boost::xtime_get(&timeToSleep, boost::TIME_UTC);
timeToSleep.sec += 2;
boost::this_thread::sleep(timeToSleep);
A_spSesion->do_writeMessage(strAnswer);
}
catch (std::exception& e)
{
std::cerr << THREAD_PROBLEM << e.what() << "\n";
}
}
会话do_writeMessage
void Session::do_writeMessage(const std::string& A_strMessage)
{
m_strMessage = A_strMessage;
m_strMessage += G_strRESPONSEEND;
// m_socket.send(boost::asio::buffer(m_strMessage)); It works correctly
m_socket.async_send(boost::asio::buffer(m_strMessage),
boost::bind(&Session::handle_write, shared_from_this(),
boost::asio::placeholders::error)); -- after that assert
}
所以最后我遇到了asynch_send的问题......
已更新
**TCPAsyncServer**::TCPAsyncServer(boost::asio::io_service& A_ioService, short port,
: m_ioService(A_ioService), m_lIDGenerator(0),
m_clientSocket(m_ioService, tcp::endpoint(tcp::v4(),
port)),
{
SessionPtr newSession(new Session(m_ioService, m_mapSessions, ++m_lIDGenerator));
m_clientSocket.async_accept(newSession->getSocket(),
boost::bind(&TCPAsyncServer::handle_ClientAccept, this,
newSession, boost::asio::placeholders::error));
会话构造
Session::Session(boost::asio::io_service& A_ioService, std::map<long, boost::shared_ptr<Session> >& A_mapSessions, long A_lId)
: m_socket(A_ioService), m_mapSessions(A_mapSessions), m_lIdentifier(A_lId), m_ioService(A_ioService)
{}
会话成员
std::map<long, boost::shared_ptr<Session> >& m_mapSessions;
long m_lIdentifier;
boost::asio::ip::tcp::socket m_socket;
boost::asio::io_service& m_ioService;
答案 0 :(得分:2)
使用prepare
从套接字读取和写入时,您需要使用consume
,commit
和asio::streambuf
。文档describes以及示例。根据您的示例代码,如果您这样做,对我来说并不明显。
写
boost::asio::streambuf b;
std::ostream os(&b);
os << "Hello, World!\n";
// try sending some data in input sequence
size_t n = sock.send(b.data());
b.consume(n); // sent data is removed from input sequence
读
boost::asio::streambuf b;
// reserve 512 bytes in output sequence
boost::asio::streambuf::mutable_buffers_type bufs = b.prepare(512);
size_t n = sock.receive(bufs);
// received data is "committed" from output sequence to input sequence
b.commit(n);
std::istream is(&b);
std::string s;
is >> s;
答案 1 :(得分:1)
如果您使用的是async_read / async_read_until,则无需为streambuf指定大小,但需要确保读入的数据不大于最大允许大小。关于“迭代器越界”问题;我发现告诉asio在读取时已经读取会导致asio读取的streambuf的竞争条件导致断言错误:
断言“迭代器越界”
您可以使用以下内容:
strand_.wrap(boost :: bind(&amp; your_class :: handle_read,this, asio :: placeholders :: error,asio :: placeholders :: bytes_transferred)));
帮助同步你的线程但是你必须小心不要“包装”已经运行的东西以及对共享数据的访问。
HTH