2011-03-24 7 views
0

주기적 호출 asio :: async_write() 데이터가 수신 지점에서 손상되었습니다.끝점에서의 데이터 손상

그러나 asio :: async_write() 호출 사이에 1ms 이내에 일시 중지를 삽입하면 데이터가 올바르게 읽혀집니다. 이 문제와

예 : 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 질문에 비해 너무 큰 경우 재현 가능한 예제로 줄이십시오. 문제를 디버그하는 데 도움이됩니다. –

+0

이 코드의 크기를 줄일 수 없으므로이 코드의 모든 부분이 서로 연결됩니다. 나는 실행의 노선을 이해하는 것이 너무 어려울 것이라고 생각한다. – niXman

+0

사람이 포함되어 있어도 zip 파일을 다운로드하지 않습니다. 그 일을 돕기 위해 우리 측에서 추가 작업이 필요합니다. 문제를 더 작은 예제로 줄임으로써 도움을 주실 수 있습니다 ** ** 도움이 필요합니다. 이는 문제를 찾는 데 도움이되는 귀중한 디버깅 기술입니다. 클라이언트 쪽에서 –

답변

2

동시에 다른 스레드에서 같은 소켓에,이 수 보낼 경우 최상위 용도, 스레딩 등

체크 표시되지 않는 예 문제가된다. 순차적으로 수행하십시오

+0

나는 단 하나의 작업자 스레드를 사용합니다. 이 스레드에서 소켓에 쓰려고합니다. 클라이언트 : http://liveworkspace.org/code/f9cd4a02b005413df2d085fae7a7f67a 서버 : http://liveworkspace.org/code/1bd1556975d720997e183cb93de7061b – niXman

+0

+1 나는 스레딩 문제를 생각한다. Asio 사용 규칙 1 : 두 개 이상의 스레드를 사용하기 전에 먼저 단일 스레드 프로그램이 올바르게 작동하도록하십시오. –

+0

스레딩에는 문제가 없습니다. 확실해. 멀티 스레딩 문제가 있으면 어디 있는지 보여주세요. – niXman

0

async_read를 사용하고 async_read 핸들러에서 async_read를 다시 호출하므로 (핸들러 이후에 정리할 시간이 없음)이 경우 데이터 손상이 발생할 가능성이 큽니다.

관련 : boost::asio : data corruption