2011-03-24 85 views
0

在循環調用asio :: async_write()數據在接收點損壞。端點上的數據損壞

但是,如果在調用asio :: async_write()之間插入1 ms的暫停,那麼數據將被正確讀取。

例這樣的問題: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_ 
+0

請在這裏發佈你的代碼,而不是對可能無法在未來的某一時刻存在的外部網站。如果代碼對於SO問題太大,請將其縮短爲可重現的示例。它將幫助您調試問題。 – 2011-03-24 13:51:38

+0

我無法縮小此代碼的大小,導致此代碼的所有部分彼此鏈接。我認爲這太難理解執行線了。 – niXman 2011-03-24 14:02:11

+0

包括我自己在內的人不會下載zip文件。這需要額外的工作來幫助你。您需要**幫助我們**通過將問題簡化爲更小的示例來幫助您。這是一個非常寶貴的調試技巧,可以幫助您找到問題所在。 – 2011-03-24 16:27:02

回答

2

你的例子並不表明頂級用法,線程等

檢查,如果你從不同的線程同時發送到同一個插座,這樣可以成爲一個問題。按順序執行

+0

在客戶端我只使用一個工作線程。我在這個線程中寫入套接字。 客戶端:http://liveworkspace.org/code/f9cd4a02b005413df2d085fae7a7f67a 服務器:http://liveworkspace.org/code/1bd1556975d720997e183cb93de7061b – niXman 2011-03-24 14:35:48

+0

+1我懷疑一個線程問題。使用Asio的規則1:在使用多個線程之前,先讓單線程程序正確工作。 – 2011-03-24 16:28:37

+0

線程沒有問題。我確定。如果你看到多線程的任何問題,請告訴我在哪裏。 – niXman 2011-03-25 15:34:09

0

這種情況下的數據損壞很可能是因爲您正在使用async_read,並且在async_read處理程序內部再次調用async_read(在處理程序後沒有時間清理)。

相關:boost::asio : data corruption