2013-04-25 4 views
0

Boost Asio을 사용하여 직렬 포트에서 가변 길이 메시지를 읽으 려합니다. 나는 그 행이 유휴 상태인지를 충분히 읽고 충분히 기다리고 싶지만 완전히 차단하고 싶지는 않다.부스트 Asio를 사용하여 직렬 포트에서 메시지 읽기

다음 코드는 지금까지 무엇을하고, 나는 그것을 테스트하는 과정에서 오전 :

long readData(void *_pData, unsigned long _uSize, size_t millis) 
{ 
    size_t n = 0; // n will return the message size. 
    if (millis > 0) // millis is the acceptable idle time, 0 is invalid in my case. 
    { 
     size_t uBytesTransferred = 0; 
     boost::asio::deadline_timer timeout(m_ioService); 
     ReadCallback readCallback(uBytesTransferred, timeout); 
     WaitCallback waitCallback(m_port); 

     while (_uSize - (unsigned long)n > 0) 
     { 
      // Setup asynchronous read with timeout 
      m_ioService.reset(); 
      m_port.async_read_some(boost::asio::buffer((char*)_pData + n, _uSize - (unsigned long)n), readCallback); 
      timeout.expires_from_now(boost::posix_time::milliseconds(millis)); 
      timeout.async_wait(waitCallback); 

      // Block until asynchronous callbacks are finished 
      m_ioService.run(); 

      // Continue if any bytes were received, stop otherwise 
      if (uBytesTransferred > 0) 
      { 
       n += uBytesTransferred; 
       m_uBytesReceived += uBytesTransferred; 
      } 
      else 
      { 
       break; 
      } 
     } 
    } 
    return n; 
} 

내가이이 일을 올바른 방법이 있는지 알고 싶습니다 (즉, 읽기입니다 라인이 유휴 상태가 될 때까지) 부스트 Asio? 당신은 당신이 "완전히 차단하지 않는다"고 말할 때

struct ReadCallback 
{ 
    ReadCallback(std::size_t &_uBytesTransferred, boost::asio::deadline_timer &_timeout) 
     :m_uBytesTransferred(_uBytesTransferred), m_timeout(_timeout) 
    {} 

    void operator()(const boost::system::error_code &_error, std::size_t _uBytesTransferred) 
    { 
     m_uBytesTransferred = _uBytesTransferred; 
     if (!_error && (_uBytesTransferred > 0)) 
     { 
      m_timeout.cancel(); 
     } 
    } 

    std::size_t      &m_uBytesTransferred; 
    boost::asio::deadline_timer  &m_timeout; 

    private: 
     ReadCallback(); 
     ReadCallback &operator=(const ReadCallback&); 
}; 

struct WaitCallback 
{ 
    WaitCallback(boost::asio::serial_port &_port) 
     :m_port(_port) 
    {} 

    void operator()(const boost::system::error_code &_error) 
    { 
     if (!_error) 
     { 
      m_port.cancel(); 
     } 
    } 

    boost::asio::serial_port &m_port; 

    private: 
     WaitCallback(); 
     WaitCallback &operator=(const WaitCallback&); 
}; 
+0

올바르게 컴파일되고 작동합니까? 그렇다면 괜찮습니다. 어쨌든 권장되는 접근법은 asio 예제에서 찾을 수 있습니다. http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/examples.html –

+0

예. 컴파일됩니다. arduino를 사용하여 데이터를 생성하여 테스트 할 수 있습니다. 일부 데이터가 손실 된 것처럼 보입니다. –

+0

이제 부스트 스레드를 사용하여 직렬 포트에서 데이터를 읽고 버퍼링하십시오. 이제 직렬 데이터를 스트림으로 읽을 수 있지만 엿볼 수 있고 비 차단 및 읽기 차단 기능을 사용할 수 있습니다. –

답변

0

이제 부스트 스레드를 사용하여 직렬 포트에서 데이터를 읽고 버퍼링하십시오. 이제 직렬 데이터를 스트림으로 읽을 수 있지만 엿볼 수 있고 비 차단 및 읽기 차단 기능을 사용할 수 있습니다.

부스트 스레드에서 직렬 IO를 래핑했습니다. 원하는대로 asio 콜백을 수행 할 수 없었습니다. 이제 스레드에서 읽기 데이터를 버퍼링하고 있지만 대기 시간을 가능한 한 낮게 유지하기 위해 블로킹 쓰기를 사용합니다.

0

, 당신이 소켓을 처리하기 위해 별도의 쓰레드를 생성 더 좋을 수 있음을 시사 I/O : 여기

내 콜백 핸들러입니다 . 그런 식으로 메인 스레드를 다른 처리에 사용할 수 있습니다. 내 클라이언트에서 2 스레드를 사용하고 있습니다. 하나의 스레드는 서버로부터 수신 된 메시지를 처리하고 다른 스레드는 서버로 메시지를 처리합니다. 내 의뢰인이 여러 서버와 대화합니다. 코드는 다음과 같습니다.

#include "StdAfx.h" 
#include "SSLSocket.h" 

boost::shared_ptr<boost::asio::io_service> SSLSocket::IOService; 
bool SSLSocket::LobbySocketOpen = false; 
SSLSocket* SSLSocket::pSSLLobby = 0; 
int SSLSocket::StaticInit = 0; 
Callback SSLSocket::CallbackFunction; 
BufferManagement SSLSocket::BufMang; 
volatile bool SSLSocket::ReqAlive = true; 
Logger SSLSocket::Log; 
HANDLE SSLSocket::hEvent; 
bool SSLSocket::DisplayInHex; 
ConcurrentMsgQueue SSLSocket::SendMsgQ; 
bool SSLSocket::RcvThreadCreated = 0; 
BufferManagement* Message::pBufMang; 
bool SSLSocket::ShuttingDown = false; 
std::vector<SSLSocket *> SocketList; 

SSLSocket::SSLSocket(const bool logToFile, const bool logToConsole, const bool displayInHex, 
    const LogLevel levelOfLog, const string& logFileName, const int bufMangLen) : pSocket(0) 
{ 
    // SSLSocket Constructor. 
    // If the static members have not been intialized yet, then initialize them. 
    LockCode = new Lock(); 
    if (!StaticInit) 
    { 
     SocketList.push_back(this); 
     DisplayInHex = displayInHex; 
     BufMang.Init(bufMangLen); 
     Message::SetBufMang(&BufMang); 
     // This constructor enables logging according to the vars passed in. 
     Log.Init(logToFile, logToConsole, levelOfLog, logFileName); 
     StaticInit = 1; 
     hEvent = CreateEvent(NULL, false, false, NULL); 
     // Define the ASIO IO service object. 
     // IOService = new boost::shared_ptr<boost::asio::io_service>(new boost::asio::io_service); 
     boost::shared_ptr<boost::asio::io_service> IOServ(new boost::asio::io_service); 
     IOService = IOServ; 
     pSSLLobby = this; 
    } 
} 

SSLSocket::~SSLSocket(void) 
{ 
    if (pSocket) 
     delete pSocket; 
    if (--StaticInit == 0) 
     CloseHandle(hEvent); 
} 

void SSLSocket::Connect(SSLSocket* psSLS, const string& serverPath, string& port) 
{ 
    // Connects to the server. 
    // serverPath - specifies the path to the server. Can be either an ip address or url. 
    // port - port server is listening on. 
    // 
    try 
    { 
     LockCode->Acquire(); // Single thread the code. 
     // Locking CodeLock(SocketLock); // Single thread the code. 
     // If the user has tried to connect before, then make sure everything is clean before trying to do so again. 
     if (pSocket) 
     { 
     delete pSocket; 
     pSocket = 0; 
     }                         
     // If serverPath is a URL, then resolve the address. 
     if ((serverPath[0] < '0') || (serverPath[0] > '9')) // Assumes that the first char of the server path is not a number when resolving to an ip addr. 
     { 
     // Create the resolver and query objects to resolve the host name in serverPath to an ip address. 
     boost::asio::ip::tcp::resolver resolver(*IOService); 
     boost::asio::ip::tcp::resolver::query query(serverPath, port); 
     boost::asio::ip::tcp::resolver::iterator EndpointIterator = resolver.resolve(query); 
     // Set up an SSL context. 
     boost::asio::ssl::context ctx(*IOService, boost::asio::ssl::context::tlsv1_client); 
     // Specify to not verify the server certificiate right now. 
     ctx.set_verify_mode(boost::asio::ssl::context::verify_none); 
     // Init the socket object used to initially communicate with the server. 
     pSocket = new boost::asio::ssl::stream<boost::asio::ip::tcp::socket>(*IOService, ctx); 
     // 
     // The thread we are on now, is most likely the user interface thread. Create a thread to handle all incoming socket work messages. 
     // Only one thread is created to handle the socket I/O reading and another thread is created to handle writing. 
     if (!RcvThreadCreated) 
     { 
      WorkerThreads.create_thread(boost::bind(&SSLSocket::RcvWorkerThread, this)); 
      RcvThreadCreated = true; 
      WorkerThreads.create_thread(boost::bind(&SSLSocket::SendWorkerThread, this)); 
     } 
     // Try to connect to the server. Note - add timeout logic at some point. 
     boost::asio::async_connect(pSocket->lowest_layer(), EndpointIterator, 
      boost::bind(&SSLSocket::HandleConnect, this, boost::asio::placeholders::error)); 
     } 
     else 
     { 
     // serverPath is an ip address, so try to connect using that. 
     // 
     // Create an endpoint with the specified ip address. 
     const boost::asio::ip::address IP(boost::asio::ip::address::from_string(serverPath)); 
     int iport = atoi(port.c_str()); 
     const boost::asio::ip::tcp::endpoint EP(IP, iport); 
     // Set up an SSL context. 
     boost::asio::ssl::context ctx(*IOService, boost::asio::ssl::context::tlsv1_client); 
     // Specify to not verify the server certificiate right now. 
     ctx.set_verify_mode(boost::asio::ssl::context::verify_none); 
     // Init the socket object used to initially communicate with the server. 
     pSocket = new boost::asio::ssl::stream<boost::asio::ip::tcp::socket>(*IOService, ctx); 
     // 
     // Try to connect to the server. Note - add timeout logic at some point. 
     //pSocket->core_.engine_.do_connect(void*, int); 
     // pSocket->next_layer_.async_connect(EP, &SSLSocket::HandleConnect) 
     // pSocket->next_layer().async_connect(EP, &SSLSocket::HandleConnect); 
     boost::system::error_code EC; 
     pSocket->next_layer().connect(EP, EC); 
     if (EC) 
     { 
      // Log an error. This worker thread should exit gracefully after this. 
      stringstream ss; 
      ss << "SSLSocket::Connect: connect failed to " << sClientIp << " : " << uiClientPort << ". Error: " << EC.message() + ".\n"; 
      Log.LogString(ss.str(), LogError); 
     } 
     HandleConnect(EC); 
     // boost::asio::async_connect(pSocket->lowest_layer(), EP, 
     // boost::bind(&SSLSocket::HandleConnect, this, boost::asio::placeholders::error)); 
     } 
    } 
    catch (std::exception& e) 
    { 
     stringstream ss; 
     ss << "SSLSocket::Connect: threw an error - " << e.what() << ".\n"; 
     Log.LogString(ss.str(), LogError); 
     Stop(); 
    } 
    LockCode->Release(); 
} 

void SSLSocket::SendToServer(const int bytesInMsg, Byte* pBuf) 
{ 
    // This method creates a msg object and saves it in the SendMsgQ object. 
    // sends the number of bytes specified by bytesInMsg in pBuf to the server. 
    // 
    Message* pMsg = Message::GetMsg(this, bytesInMsg, pBuf); 
    SendMsgQ.Push(pMsg); 
    // Signal the send worker thread to wake up and send the msg to the server. 
    SetEvent(hEvent); 
} 


void SSLSocket::SendWorkerThread(SSLSocket* psSLS) 
{ 
    // This thread method gets called to process the messages to be sent to the server. 
    // 
    // Since this has to be a static method, call a method on the class to handle server requests. 
    psSLS->ProcessSendRequests(); 
} 

void SSLSocket::ProcessSendRequests() 
{ 
    // This method handles sending msgs to the server. 
    // 
    std::stringstream ss; 
    DWORD WaitResult; 
    Log.LogString("SSLSocket::ProcessSendRequests: Worker thread " + Logger::NumberToString(boost::this_thread::get_id()) + " started.\n", LogInfo); 
    // Loop until the user quits, or an error of some sort is thrown. 
    try 
    { 
     do 
     { 
     // If there are one or more msgs that need to be sent to a server, then send them out. 
     if (SendMsgQ.Count() > 0) 
     { 
      Message* pMsg = SendMsgQ.Front(); 
      SSLSocket* pSSL = pMsg->pSSL; 
      SendMsgQ.Pop(); 
      const Byte* pBuf = pMsg->pBuf; 
      const int BytesInMsg = pMsg->BytesInMsg; 
      boost::system::error_code Error; 
      LockCode->Acquire(); // Single thread the code. 
      // Locking CodeLock(SocketLock); // Single thread the code. 
      try 
      { 
       boost::asio::async_write(*pSSL->pSocket, boost::asio::buffer(pBuf, BytesInMsg), boost::bind(&SSLSocket::HandleWrite, this, 
        boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); 
      } 
      catch (std::exception& e) 
      { 
       stringstream ss; 
       ss << "SSLSocket::ProcessSendRequests: threw an error - " << e.what() << ".\n"; 
       Log.LogString(ss.str(), LogError); 
       // Stop(); 
      } 
      ss.str(std::string()); 
      ss << "SSLSocket::ProcessSendRequests: # bytes sent = " << BytesInMsg << "\n"; 
      Log.LogString(ss.str(), LogDebug2); 
      Log.LogBuf(pBuf, BytesInMsg, DisplayInHex, LogDebug3); 
      LockCode->Release(); 
     } 
     else 
     { 
      // Nothing to send, so go into a wait state. 
      WaitResult = WaitForSingleObject(hEvent, INFINITE); 
      if (WaitResult != 0L) 
      { 
       Log.LogString("SSLSocket::ProcessSendRequests: WaitForSingleObject event error. Code = " + Logger::NumberToString(GetLastError()) + ". \n", LogError); 
      } 
     } 
     } while (ReqAlive); 
     Log.LogString("SSLSocket::ProcessSendRequests: Worker thread " + Logger::NumberToString(boost::this_thread::get_id()) + " done.\n", LogInfo); 
    } 
    catch (std::exception& e) 
    { 
     stringstream ss; 
     ss << "SSLSocket::ProcessSendRequests: threw an error - " << e.what() << ".\n"; 
     Log.LogString(ss.str(), LogError); 
     Stop(); 
    } 
} 

void SSLSocket::HandleWrite(const boost::system::error_code& error, size_t bytesTransferred) 
{ 
    // This method is called after a msg has been written out to the socket. Nothing to do really since reading is handled by the HandleRead method. 
    // 
    std::stringstream ss; 
    try 
    { 
     if (error) 
     { 
     ss << "SSLSocket::HandleWrite: failed - " << error.message() << ".\n"; 
     Log.LogString(ss.str(), LogError); 
     Stop(); 
     } 
    } 
    catch (std::exception& e) 
    { 
     stringstream ss; 
     ss << "SSLSocket::HandleHandshake: threw an error - " << e.what() << ".\n"; 
     Log.LogString(ss.str(), LogError); 
     Stop(); 
    } 
} 

void SSLSocket::RcvWorkerThread(SSLSocket* psSLS) 
{ 
    // This is the method that gets called when the receive thread is created by this class. 
    // This thread method focuses on processing messages received from the server. 
    // 
    // Since this has to be a static method, call a method on the class to handle server requests. 
    psSLS->InitAsynchIO(); 
} 

void SSLSocket::InitAsynchIO() 
{ 
    // This method is responsible for initiating asynch i/o. 
    boost::system::error_code Err; 
    string s; 
    stringstream ss; 
    // 
    try 
    { 
     ss << "SSLSocket::InitAsynchIO: Worker thread - " << Logger::NumberToString(boost::this_thread::get_id()) << " started.\n"; 
     Log.LogString(ss.str(), LogInfo); 
     // Enable the handlers for asynch i/o. The thread will hang here until the stop method has been called or an error occurs. 
     // Add a work object so the thread will be dedicated to handling asynch i/o. 
     boost::asio::io_service::work work(*IOService); 
     IOService->run(); 
     Log.LogString("SSLSocket::InitAsynchIO: receive worker thread done.\n", LogInfo); 
    } 
    catch (std::exception& e) 
    { 
     stringstream ss; 
     ss << "SSLSocket::InitAsynchIO: threw an error - " << e.what() << ".\n"; 
     Log.LogString(ss.str(), LogError); 
     Stop(); 
    } 
} 

void SSLSocket::HandleConnect(const boost::system::error_code& error) 
{ 
    // This method is called asynchronously when the server has responded to the connect request. 
    std::stringstream ss; 
    try 
    { 
     if (!error) 
     { 
     pSocket->async_handshake(boost::asio::ssl::stream_base::client, 
      boost::bind(&SSLSocket::HandleHandshake, this, boost::asio::placeholders::error)); 
     ss << "SSLSocket::HandleConnect: From worker thread " << Logger::NumberToString(boost::this_thread::get_id()) << ".\n"; 
     Log.LogString(ss.str(), LogInfo); 
     } 
     else 
     { 
     // Log an error. This worker thread should exit gracefully after this. 
     ss << "SSLSocket::HandleConnect: connect failed to " << sClientIp << " : " << uiClientPort << ". Error: " << error.message() + ".\n"; 
     Log.LogString(ss.str(), LogError); 
     Stop(); 
     } 
    } 
    catch (std::exception& e) 
    { 
     stringstream ss; 
     ss << "SSLSocket::InitAsynchIO: threw an error - " << e.what() << ".\n"; 
     Log.LogString(ss.str(), LogError); 
     Stop(); 
    } 
} 

void SSLSocket::HandleHandshake(const boost::system::error_code& error) 
{ 
    // This method is called asynchronously when the server has responded to the handshake request. 
    std::stringstream ss; 
    try 
    { 
     if (!error) 
     { 
     // Try to send the first message that the server is expecting. This msg tells the server we want to connect. 
     // The first 4 bytes specifies the msg length after the first 4 bytes. The next 2 bytes specifies the msg type. 
     // The next 4 bytes specifies the source code. The next 13 bytes specifies the msg "AttackPoker". 
     // The next 2 bytes specifies the locale length. The last 2 bytes specifies the locale - en for English. 
     // 
     unsigned char Msg[27] = {0x17, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x41, 
      0x74, 0x74, 0x61, 0x63, 0x6b, 0x50, 0x6f, 0x6b, 0x65, 0x72, 0x02, 0x00, 0x65, 0x6e}; 
     boost::system::error_code Err; 
     // 
     if (pSSLLobby == this) 
      LobbySocketOpen = true; 
     sClientIp = pSocket->lowest_layer().remote_endpoint().address().to_string(); 
     uiClientPort = pSocket->lowest_layer().remote_endpoint().port(); 
     ReqAlive = true; 
     // boost::asio::async_write(*pSocket, boost::asio::buffer(Msg), boost::bind(&SSLSocket::HandleFirstWrite, this, 
     // boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); 
     int Count = boost::asio::write(*pSocket, boost::asio::buffer(Msg), boost::asio::transfer_exactly(27), Err); 
     if (Err) 
     { 
      ss << "SSLSocket::HandleHandshake: write failed - " << error.message() << ".\n"; 
      Log.LogString(ss.str(), LogInfo); 
     } 
     HandleFirstWrite(Err, Count); 
     // boost::asio::async_write(pSocket, boost::asio::buffer(Msg, 27), boost::bind(&SSLSocket::HandleWrite, this, 
     // boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); 
     ss.str(""); 
     ss << "SSLSocket::HandleHandshake: From worker thread " << boost::this_thread::get_id() << ".\n"; 
     } 
     else 
     { 
     ss << "SSLSocket::HandleHandshake: failed - " << error.message() << ".\n"; 
     IOService->stop(); 
     } 
     Log.LogString(ss.str(), LogInfo); 
    } 
    catch (std::exception& e) 
    { 
     stringstream ss; 
     ss << "SSLSocket::HandleHandshake: threw an error - " << e.what() << ".\n"; 
     Log.LogString(ss.str(), LogError); 
     Stop(); 
    } 
} 

void SSLSocket::HandleFirstWrite(const boost::system::error_code& error, size_t bytesTransferred) 
{ 
    // This method is called after a msg has been written out to the socket. 
    std::stringstream ss; 
    try 
    { 
     if (!error) 
     { 
     // boost::asio::async_read(pSocket, boost::asio::buffer(reply_, bytesTransferred), boost::bind(&SSLSocket::handle_read, 
     // this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); 
     // boost::asio::async_read(pSocket, boost::asio::buffer(reply_, 84), boost::bind(&SSLSocket::handle_read, 
     // this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); 
     // Locking CodeLock(ReadLock); // Single thread the code. 
     // Signal the other threads that msgs are now ready to be sent and received. 
     // boost::asio::async_read(pSocket, boost::asio::buffer(pRepBuf), boost::asio::transfer_exactly(4), boost::bind(&SSLSocket::HandleRead, 
     // this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); 
     // 
     // Notify the UI that we are now connected. Create a 6 byte msg for this. 
     pDataBuf = BufMang.GetPtr(6); 
     BYTE* p = pDataBuf; 
     // Create msg type 500 
     *p = 244; 
     *++p = 1; 
     CallbackFunction(this, 2, (void*)pDataBuf); 
     // Get the 1st 4 bytes of the next msg, which is always the length of the that msg. 
     pDataBuf = BufMang.GetPtr(MsgLenBytes); 

     // int i1=1,i2=2,i3=3,i4=4,i5=5,i6=6,i7=7,i8=8,i9=9; 
     // (boost::bind(&nine_arguments,_9,_2,_1,_6,_3,_8,_4,_5,_7)) 
     //  (i1,i2,i3,i4,i5,i6,i7,i8,i9); 

     // boost::asio::read(*pSocket, boost::asio::buffer(pReqBuf, MsgLenBytes), boost::asio::transfer_exactly(MsgLenBytes), Err); 
     // boost::asio::async_read(pSocket, boost::asio::buffer(pReqBuf, MsgLenBytes), boost::bind(&SSLSocket::HandleRead, _1,_2,_3)) 
     // (this, pReqBuf, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred); 
     // boost::asio::async_read(*pSocket, boost::asio::buffer(reply_), boost::asio::transfer_exactly(ByteCount), boost::bind(&Client::handle_read, 
     //  this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); 
     // boost::asio::async_write(*pSocket, boost::asio::buffer(pDataBuf, MsgLenBytes), boost::bind(&SSLSocket::HandleWrite, this, 
     // boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); 
     try 
     { 
      LockCode->Acquire(); // Single thread the code. 
      // Locking CodeLock(SocketLock); // Single thread the code. 
      boost::asio::async_read(*pSocket, boost::asio::buffer(pDataBuf, MsgLenBytes), boost::bind(&SSLSocket::HandleRead, this, 
       boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); 
     } 
     catch (std::exception& e) 
     { 
      stringstream ss; 
      ss << "SSLSocket::HandleFirstWrite: threw an error - " << e.what() << ".\n"; 
      Log.LogString(ss.str(), LogError); 
      Stop(); 
     } 
     LockCode->Release(); 
     } 
     else 
     { 
     ss << "SSLSocket::HandleFirstWrite: failed - " << error.message() << ".\n"; 
     Log.LogString(ss.str(), LogError); 
     Stop(); 
     } 
    } 
    catch (std::exception& e) 
    { 
     stringstream ss; 
     ss << "SSLSocket::HandleFirstWrite: threw an error - " << e.what() << ".\n"; 
     Log.LogString(ss.str(), LogError); 
     Stop(); 
    } 
} 

void SSLSocket::HandleRead(const boost::system::error_code& error, size_t bytesTransferred) 
{ 
    // This method is called to process an incomming message. 
    // 
    std::stringstream ss; 
    int ByteCount; 
    try 
    { 
     // ss << "SSLSocket::HandleRead: From worker thread " << boost::this_thread::get_id() << ".\n"; 
     // Log.LogString(ss.str(), LogInfo); 
     // Set to exit this thread if the user is done. 
     if (!ReqAlive) 
     { 
     // IOService->stop(); 
     return; 
     } 
     if (!error) 
     { 
     // Get the number of bytes in the message. 
     if (bytesTransferred == 4) 
     { 
      ByteCount = BytesToInt(pDataBuf); 
     } 
     else 
     { 
      // Call the C# callback method that will handle the message. 
      ss << "SSLSocket::HandleRead: From worker thread " << boost::this_thread::get_id() << "; # bytes transferred = " << bytesTransferred << ".\n"; 
      Log.LogString(ss.str(), LogDebug2); 
      if (bytesTransferred > 0) 
      { 
       Log.LogBuf(pDataBuf, (int)bytesTransferred, true, LogDebug3); 
       Log.LogString("SSLSocket::HandleRead: sending msg to the C# client.\n\n", LogDebug2); 
       CallbackFunction(this, bytesTransferred, (void*)pDataBuf); 
      } 
      else 
      { 
       // # of bytes transferred = 0. Don't do anything. 
       bytesTransferred = 0; // For debugging. 
      } 
      // Prepare to read in the next message length. 
      ByteCount = MsgLenBytes; 
     } 
     pDataBuf = BufMang.GetPtr(ByteCount); 
     boost::system::error_code Err; 
     // boost::asio::async_read(pSocket, boost::asio::buffer(pDataBuf, ByteCount), boost::bind(&SSLSocket::HandleRead, 
      // this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); 
     LockCode->Acquire(); // Single thread the code. 
     // Locking CodeLock(SocketLock); // Single thread the code. 
     try 
     { 
      boost::asio::async_read(*pSocket, boost::asio::buffer(pDataBuf, ByteCount), boost::bind(&SSLSocket::HandleRead, 
       this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); 
      // boost::asio::read(pSocket, boost::asio::buffer(reply_), boost::asio::transfer_exactly(ByteCount), Err); 
     } 
     catch (std::exception& e) 
     { 
      stringstream ss; 
      ss << "SSLSocket::HandleRead: threw this error - " << e.what() << ".\n"; 
      Log.LogString(ss.str(), LogError); 
      // Stop(); 
     } 
     LockCode->Release(); 
     } 
     else 
     { 
     Log.LogString("SSLSocket::HandleRead failed: " + error.message() + "\n", LogError); 
     Stop(); 
     } 
    } 
    catch (std::exception& e) 
    { 
     stringstream ss; 
     ss << "SSLSocket::HandleRead: threw an error - " << e.what() << ".\n"; 
     Log.LogString(ss.str(), LogError); 
     Stop(); 
    } 
} 

void SSLSocket::Stop() 
{ 
    // This method calls the shutdown method on the socket in order to stop reads or writes that might be going on. If this is not done, then an exception will be thrown 
    // when it comes time to delete this object. 
    // 
    boost::system::error_code EC; 
    try 
    { 
     // This method can be called from the handler as well. So once the ShuttingDown flag is set, don't go throught the same code again. 
     if (ShuttingDown) 
     return; 
     LockCode->Acquire(); // Single thread the code. 
     if (!ShuttingDown) 
     { 
     ShuttingDown = true; 
     pSocket->next_layer().cancel(); 
     pSocket->shutdown(EC); 
     if (EC) 
     { 
      stringstream ss; 
      ss << "SSLSocket::Stop: socket shutdown error - " << EC.message() << ".\n"; 
      // Log.LogString(ss.str(), LogError); // Usually get this - probably not an error. 
     } 
     else 
     { 
      pSocket->next_layer().close(); 
     } 
     delete pSocket; 
     pSocket = 0; 
     ReqAlive = false; 
     SetEvent(hEvent); 
     IOService->stop(); 
     LobbySocketOpen = false; 
     WorkerThreads.join_all(); 
     } 
     LockCode->Release(); 
     delete LockCode; 
     LockCode = 0; 
    } 
    catch (std::exception& e) 
    { 
     stringstream ss; 
     ss << "SSLSocket::HandleRead: threw an error - " << e.what() << ".\n"; 
     Log.LogString(ss.str(), LogError); 
     Stop(); 
    } 
} 
+0

부스트 스레드에서 serial io를 래핑했습니다. 원하는대로 asio 콜백을 수행 할 수 없었습니다. 이제 스레드에서 읽기 데이터를 버퍼링하고 있지만 대기 시간을 가능한 한 낮게 유지하기 위해 블로킹 쓰기를 사용합니다. –

관련 문제