ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 수신 오류로 착각한 송신 오류
    프로그래밍/의문 2015. 6. 10. 05:18
    반응형

    // 2015/06/10 ReceiveStream에서 오류가 있어서 콜백함수 호출때 프로그램이 뻗는 오류가 발견되었다.(오류0)

    // 오류0에 대한 해결: OnSessionReceive에서 데이터를 처리하고 세션으로 다시 Send를 하는데 그 부분에서 오류가 있었다. 메모리의 잘못된 사용으로 인한 오류였다.


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47

    void Session::Receive() 
    {
      // 
      /** @note: Receive 함수의 구현 중점(2015/06/05)
      * 0. 데이터의 복사를 최소화: Receive 버퍼를 그대로 이용할 수 있다면 그대로 이용한다.
      * 1. 신경 쓸 필요 없는 버퍼의 크기: 버퍼가 가득 찼는데도 처리가 없다면 버퍼는 자동으로 늘어나고 수신을 계속한다.
      */
     
      m_socket->async_receive(asio::buffer(m_receiveStream.Writer(), m_receiveStream.WritableSize()),
        m_strand.wrap(
          [this](const system::error_code& error, size_t bytesTransferred) { 
     
        if (!error)
        {// 정상 수신
          m_receiveStream.IncreaseWriter(bytesTransferred);
     
          auto reader = m_receiveStream.Reader();
          auto readableSize = m_receiveStream.ReadableSize();
     
          const auto processed = this->m_eventReceiver->OnSessionReceive(this, m_receiveStream.Reader(), m_receiveStream.ReadableSize());
     
          if (processed != 0)
          {// 데이터를 처리했다면
            m_receiveStream.IncreaseReader(processed); // 처리된 만큼 읽기 인덱스를 뒤로 이동한다.
          }
          else
          {// 데이터가 처리되지 않았을 경우
           // 남은 수신 버퍼의 크기를 검사한다.
            if (m_receiveStream.WritableSize() == 0)
            {// 남은 수신 버퍼의 크기가 0이다
              const auto trimmed = m_receiveStream.Trim(); // 트림(여유 공간 확보)을 시도한다.
     
              if (trimmed == 0)
              {// 트림되지 않았다면 버퍼 자체를 확장한다.
                m_receiveStream.Extend();
              }
            }
          }
     
          this->Receive(); // 수신을 계속한다.
        }
        else
        {// 수신 오류
          this->m_eventReceiver->OnSessionError(this, error); // 오류 알림
        }
     
      }));
    cs



    문제의 Send 부분. 

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    void Session::Send(const void* buffer, size_t size) // 최적화 과정이 덜 되었다. shared_ptr은 프로토타입을 위해 임시적으로 사용했다. 이 함수가 문제
    {
      auto sendData = std::make_shared<std::vector<char>>(size);
     
      std::memcpy(sendData->data(), buffer, size); // 오류가 있던 부분 std::memcpy(sendData.get(), buffer, size)
      
      m_socket->async_send(
        asio::buffer(sendData->data(), size), 
        m_strand.wrap([this, sendData](const system::error_code& error, size_t bytesTransferred) { // 여기서 sendData가 지워짐
     
        this->SendCompletionRoutine(error, bytesTransferred);
      } 
      ));
    }
    cs


    프로토타입을 만들고 이후 최적화를 하려던 과정이었다. 빠른 동작 확인을 위해 make_shared와 vector를 조합해서 send buffer 부분을 만들었었는데 잘못된 사용을 하고 있었다. Receive 부분을 지나자 오류가 발생했기에 오류가 Receive쪽에서 발생한줄 알고 Receive Stream과 Server의 로직 부분을 한참을 봤었다.

    반응형
Designed by Tistory.