端点数据损坏

发布于 2024-10-25 10:04:40 字数 4775 浏览 7 评论 0原文

在循环调用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

叹倦 2024-11-01 10:04:40

您的示例没有显示顶级用法、线程等。

检查您是否同时从不同线程发送到同一套接字,这可能是一个问题。按顺序做

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

情话难免假 2024-11-01 10:04:40

在这种情况下,数据损坏很可能是因为您正在使用 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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文