端点数据损坏
在循环调用 asio::async_write() 时,接收点数据损坏。
但是,如果在调用 asio::async_write() 之间插入 1 毫秒的暂停,则数据将被正确读取。
此问题的示例:http://rghost.ru/4908432
#ifndef _header_hpp_included_
#define _header_hpp_included_
#include <iostream>
#include <sstream>
#include <cstdio>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp>
#include <boost/lexical_cast.hpp>
enum { recv_buffer_size = 13 };
enum { send_buffer_size = 13 };
volatile size_t counter = 0;
/***************************************************************************/
void client_readed(boost::asio::ip::tcp::socket&, boost::shared_array<char>, const boost::system::error_code&);
/** client read the reply from the server */
void client_read(boost::asio::ip::tcp::socket& sock) {
boost::shared_array<char> buf(new char[recv_buffer_size]);
boost::asio::async_read(
sock,
boost::asio::buffer(buf.get(), recv_buffer_size),
boost::bind(
&client_readed,
boost::ref(sock),
buf,
boost::asio::placeholders::error
)
);
}
/** when the whole packet is read client check it's index */
void client_readed(boost::asio::ip::tcp::socket& sock, boost::shared_array<char> buf, const boost::system::error_code& e) {
if ( e ) {
if ( !counter ) return;
std::cout << "read handler: " << e.message() << std::endl;
return;
}
counter--;
#ifdef _my_debug_
printf("client_readed(): %s", buf.get());
fflush(stdout);
#endif
static size_t idx = 0;
size_t tmp = 0;
char* p = strchr(buf.get(), ':');
if ( p ) {
p++;
sscanf(p, "%8d", &tmp);
} else {
throw std::runtime_error("input data error!");
}
if ( idx != tmp ) {
std::ostringstream os;
os << "read error. expected " << idx << " get " << tmp;
throw std::runtime_error(os.str());
}
idx++;
client_read(sock);
}
/***************************************************************************/
void writen(boost::shared_array<char>, const boost::system::error_code&);
/** client send the packet to the server */
void start_write(boost::asio::ip::tcp::socket& sock, boost::shared_array<char> buf) {
counter++;
boost::asio::async_write(
sock,
boost::asio::buffer(buf.get(), send_buffer_size),
boost::bind(
&writen,
buf,
boost::asio::placeholders::error
)
);
}
void writen(boost::shared_array<char> buf, const boost::system::error_code& e) {
if ( e ) {
std::cout << "writen(): " << e.message() << std::endl;
}
}
/***************************************************************************/
void server_readed(boost::asio::ip::tcp::socket&, boost::shared_array<char>, const boost::system::error_code&);
/** async reading incoming packet at the server side */
void server_read(boost::asio::ip::tcp::socket& sock) {
boost::shared_array<char> buf(new char[recv_buffer_size]);
boost::asio::async_read(
sock,
boost::asio::buffer(buf.get(), recv_buffer_size),
boost::bind(
&server_readed,
boost::ref(sock),
buf,
boost::asio::placeholders::error
)
);
}
/** when the whole packet is read send it back to the client */
void server_readed(boost::asio::ip::tcp::socket& sock, boost::shared_array<char> buf, const boost::system::error_code& e) {
if ( e ) {
std::cout << "read handler: " << e.message() << std::endl;
return;
}
#ifdef _my_debug_
printf("server_readed(): %s", buf.get());
#endif
static const char* ptr = "sc:";
memcpy(buf.get(), ptr, strlen(ptr));
start_write(sock, buf);
server_read(sock);
}
/***************************************************************************/
/** this functional object execute in the boost::thread at the client side */
struct async_test {
async_test(boost::asio::ip::tcp::socket& sock, volatile bool& run)
:_sock(sock),
_run(run)
{}
void operator()() {
for ( size_t idx = 0; _run; ++idx ) {
boost::shared_array<char> buf(new char[send_buffer_size]);
sprintf(buf.get(), "cs:%8d\n", idx);
start_write(_sock, buf);
}
}
private:
boost::asio::ip::tcp::socket& _sock;
volatile bool& _run;
};
/***************************************************************************/
#endif // _header_hpp_included_
In cyclic calling asio::async_write() data corrupted at the receiving point.
If, however, between calls asio::async_write() insert a pause in 1 ms then the data will be read correctly.
Example with this problem: http://rghost.ru/4908432
#ifndef _header_hpp_included_
#define _header_hpp_included_
#include <iostream>
#include <sstream>
#include <cstdio>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp>
#include <boost/lexical_cast.hpp>
enum { recv_buffer_size = 13 };
enum { send_buffer_size = 13 };
volatile size_t counter = 0;
/***************************************************************************/
void client_readed(boost::asio::ip::tcp::socket&, boost::shared_array<char>, const boost::system::error_code&);
/** client read the reply from the server */
void client_read(boost::asio::ip::tcp::socket& sock) {
boost::shared_array<char> buf(new char[recv_buffer_size]);
boost::asio::async_read(
sock,
boost::asio::buffer(buf.get(), recv_buffer_size),
boost::bind(
&client_readed,
boost::ref(sock),
buf,
boost::asio::placeholders::error
)
);
}
/** when the whole packet is read client check it's index */
void client_readed(boost::asio::ip::tcp::socket& sock, boost::shared_array<char> buf, const boost::system::error_code& e) {
if ( e ) {
if ( !counter ) return;
std::cout << "read handler: " << e.message() << std::endl;
return;
}
counter--;
#ifdef _my_debug_
printf("client_readed(): %s", buf.get());
fflush(stdout);
#endif
static size_t idx = 0;
size_t tmp = 0;
char* p = strchr(buf.get(), ':');
if ( p ) {
p++;
sscanf(p, "%8d", &tmp);
} else {
throw std::runtime_error("input data error!");
}
if ( idx != tmp ) {
std::ostringstream os;
os << "read error. expected " << idx << " get " << tmp;
throw std::runtime_error(os.str());
}
idx++;
client_read(sock);
}
/***************************************************************************/
void writen(boost::shared_array<char>, const boost::system::error_code&);
/** client send the packet to the server */
void start_write(boost::asio::ip::tcp::socket& sock, boost::shared_array<char> buf) {
counter++;
boost::asio::async_write(
sock,
boost::asio::buffer(buf.get(), send_buffer_size),
boost::bind(
&writen,
buf,
boost::asio::placeholders::error
)
);
}
void writen(boost::shared_array<char> buf, const boost::system::error_code& e) {
if ( e ) {
std::cout << "writen(): " << e.message() << std::endl;
}
}
/***************************************************************************/
void server_readed(boost::asio::ip::tcp::socket&, boost::shared_array<char>, const boost::system::error_code&);
/** async reading incoming packet at the server side */
void server_read(boost::asio::ip::tcp::socket& sock) {
boost::shared_array<char> buf(new char[recv_buffer_size]);
boost::asio::async_read(
sock,
boost::asio::buffer(buf.get(), recv_buffer_size),
boost::bind(
&server_readed,
boost::ref(sock),
buf,
boost::asio::placeholders::error
)
);
}
/** when the whole packet is read send it back to the client */
void server_readed(boost::asio::ip::tcp::socket& sock, boost::shared_array<char> buf, const boost::system::error_code& e) {
if ( e ) {
std::cout << "read handler: " << e.message() << std::endl;
return;
}
#ifdef _my_debug_
printf("server_readed(): %s", buf.get());
#endif
static const char* ptr = "sc:";
memcpy(buf.get(), ptr, strlen(ptr));
start_write(sock, buf);
server_read(sock);
}
/***************************************************************************/
/** this functional object execute in the boost::thread at the client side */
struct async_test {
async_test(boost::asio::ip::tcp::socket& sock, volatile bool& run)
:_sock(sock),
_run(run)
{}
void operator()() {
for ( size_t idx = 0; _run; ++idx ) {
boost::shared_array<char> buf(new char[send_buffer_size]);
sprintf(buf.get(), "cs:%8d\n", idx);
start_write(_sock, buf);
}
}
private:
boost::asio::ip::tcp::socket& _sock;
volatile bool& _run;
};
/***************************************************************************/
#endif // _header_hpp_included_
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您的示例没有显示顶级用法、线程等。
检查您是否同时从不同线程发送到同一套接字,这可能是一个问题。按顺序做
your example doesn't show top-level usages, threading etc.
check if you send to the same socket from different threads simultaneously, this can be a problem. do it sequentially
在这种情况下,数据损坏很可能是因为您正在使用 async_read,并且在 async_read 处理程序内部再次调用 async_read (使其没有时间在处理程序之后进行清理)。
相关:boost::asio:数据损坏
The data corruption in this case is most likely because you are using async_read, and inside the async_read handler, are calling async_read again (giving it no time to clean up after the handler).
Related: boost::asio : data corruption