ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 논블럭 소켓으로 connect 시 EAgain만 발생하던 현상
    프로그래밍/의문 2018. 7. 3. 08:38
    반응형
    if (IsOpen())
    {
      return false;
    }

    m_nativeSocket = nn::socket::Socket(static_cast<Family>(GetProtocolFamily()), Type::Sock_Stream, Protocol::IpProto_Tcp);

    const bool opened = m_nativeSocket != SocketError;

    if (opened)
    {
      SetSocketOptions();
    }

    return opened;


    소켓을 열고, 소켓 옵션을 적용한다. 적용할 소켓 옵션은 Nonblock으로, Poll api와 함께 사용될 것이었다.


    그런데 connect를 진행했을 때, 항상 EAgain 에러가 나오더라. 하지만 에러와 무관하게 연결이 맺어졌고, 때문에 WouldBlock 같은 건가 싶어서 대수롭지 않게 넘어갔는데, 테스팅 중 서버가 켜지지 않았을 때에도 EAgain 에러가 발생하며, 연결 실패를 별도로 구분할 수 없다는 걸 알았다.


    int res = socket::Connect(m_nativeSocket, reinterpret_cast<SockAddr*>(&sockAddr), sizeof(sockAddr));
    if (res == SocketError)
    {
      Errno err = nn::socket::GetLastError();
      switch (err)
      {
      case Errno::EAgain:
      case Errno::EInProgress:
        //case Errno::EWouldBlock: == EAgain
        /*
        Errno::EAgain An auto-assigned port number was requested but no auto-assigned ports are available.
        Errno::EAgain Resources to complete the request are temporarily unavailable.
        */
        m_connectionState = ConnectionState::Connecting;
        return true;
      }
      else
      {
        m_connectionState = ConnectionState::Connected;
      }
    }


    어딘가 잘못된 거 같아서 다시 한번 nonblock 옵션 설정과, 에러 메세지에 대해서 찾아봤다가 nonblock 옵션 설정 부분이 잘못됐단 걸 알았다.


    잘못되었던 nonblock 옵션 설정 >>

    int flag = 0;
    socket::Fcntl(m_nativeSocket, FcntlCommand::F_GetFl, &flag);
    flag = flag | (int)socket::FcntlFlag::O_NonBlock;
    socket::Fcntl(m_nativeSocket, FcntlCommand::F_SetFl, flag);


    정상적으로 수정한 nonblock 옵션 설정 >>

    int flags = socket::Fcntl(m_nativeSocket, FcntlCommand::F_GetFl, 0) | O_NONBLOCK;
    socket::Fcntl(m_nativeSocket, FcntlCommand::F_SetFl, flags);


    이후 정상적으로 붙으며, 로컬 pc에 서버와 클라이언트를 동시에 띄운 경우 곧바로 연결까지 됐다.

    반응형
Designed by Tistory.