ONE QUESTION AT A TIME.

천천히 생각하고, 분명하게.

TODAY’S QUESTION711 / 1500
네트워크난이도 하5분 답변 목표 · 보강본

AcceptEx로 연결 수락을 미리 요청했습니다. 클라이언트는 연결됐는데 왜 완료가 늦을 수 있고, 완료 뒤 소켓은 어떻게 초기화하나요?

잠깐, 답변을 보기 전에
먼저 내 말로 설명해 볼까요?

답변과 점검 포인트 펼치기답변 접기
01

구두 답변

정의를 외우기보다, 원리와 조건을 연결해 설명해 보세요.

AcceptEx는 BOOL을 반환하며, 성공적으로 즉시 완료되면 TRUE입니다. 실패하면 FALSE이고 WSAGetLastError로 오류를 읽습니다. 이때 ERROR_IO_PENDING이면 작업이 성공적으로 시작되어 나중에 완료되는 것이므로 제출 실패로 정리하면 안 됩니다. AcceptEx는 연결을 수락하고 주소 정보를 채우며, 지정한 수신 데이터 길이가 0이면 데이터 대기 없이 연결 도착 시 완료될 수 있습니다. 길이가 0보다 크면 연결과 첫 데이터 수신이 결합되지만, 지정 길이를 모두 채워야만 완료된다고 단정하지 않고 실제 완료·오류 계약을 확인하겠습니다.

출력 버퍼와 완료 조건

AcceptEx에는 듣기 소켓, 아직 bind·connect하지 않은 수락 소켓, 출력 버퍼, 수신 데이터 길이, 로컬·원격 주소 예약 길이, OVERLAPPED가 들어갑니다. 수신 데이터는 버퍼 앞부분에, 주소 정보는 뒷부분의 내부 형식에 기록됩니다. 로컬·원격 주소 예약은 각각 해당 전송의 최대 주소 길이보다 16바이트 이상 커야 하며, TCP IPv4의 sockaddr_in이라면 각각 최소 32바이트를 예약합니다. 주소 예약 영역은 초기 데이터 영역과 별개이므로 전체 버퍼 크기도 dwReceiveDataLength + local + remote 이상으로 계산합니다. 이를 데이터·주소 영역 분리라고 부르겠습니다.

완료 바이트 수는 비동기라면 완료 통지에서 얻고, 동기 완료일 때만 lpdwBytesReceived가 설정될 수 있습니다. 첫 데이터가 포함된 경우에도 그 바이트가 애플리케이션 프로토콜상 완전한 프레임이라는 뜻은 아니므로 이후 프레이밍 파서로 넘깁니다. 주소는 버퍼의 오프셋을 자체 계산해 읽지 않고 AcceptEx에 사용한 동일한 길이 인자를 넣어 GetAcceptExSockaddrs로 로컬·원격 sockaddr를 추출합니다. 이것이 데이터 시작 위치와 주소 추출을 섞지 않는 경계입니다.

완료 뒤 소켓 초기화와 재제출

AcceptEx 완료 뒤에는 SO_UPDATE_ACCEPT_CONTEXT를 수락 소켓에 설정하고, 필요한 소켓 옵션과 IOCP 연결·수신 컨텍스트를 준비합니다. 수락 소켓은 듣기 소켓의 속성을 자동으로 상속한다고 가정하지 않습니다. 성공·ERROR_IO_PENDING·그 밖의 즉시 오류를 나눠 처리하고, 오류나 빠른 연결 종료에서는 수락 소켓·버퍼·OVERLAPPED를 정리한 뒤 다음 수락을 보충합니다. 미완료 수락을 취소할 때도 완료 drain 전에는 컨텍스트를 재사용하지 않습니다.

테스트는 연결만 하고 데이터를 보내지 않는 클라이언트, 초기 데이터의 부분 도착, 빠른 FIN/RST, 주소 추출, SO_UPDATE_ACCEPT_CONTEXT 실패, backlog와 미리 제출한 수의 차이를 포함합니다. AcceptEx의 TRUE나 완료 포트 패킷은 인증·애플리케이션 세션 성립이 아니므로 이후 프로토콜 timeout과 인가를 별도로 둡니다.

추가 조건과 판단

수락 요청 개수와 listen backlog도 구분하겠습니다. backlog는 커널의 연결 수립·수락 대기와 관련되고, 미리 제출한 AcceptEx 슬롯은 애플리케이션이 완료를 받을 소켓과 버퍼를 준비한 수입니다. 연결만 한 뒤 데이터를 보내지 않는 클라이언트가 초기 수신을 포함한 슬롯을 오래 붙잡으면 다음 연결을 처리할 여유가 줄 수 있습니다. 그래서 인증 전 연결 수, 첫 데이터 대기 시간, 수락 슬롯 보충률을 함께 제한합니다.

즉시 TRUE가 반환되더라도 완료 통지 생략을 설정하지 않은 IOCP 경로에서는 완료 패킷을 별도로 받을 수 있습니다. 제출 전에 컨텍스트와 미완료 예약을 확보하고, 즉시 실패일 때만 되돌리며 정상 완료·취소 완료는 한 경로에서 정리해야 합니다. 듣기 소켓에 제출한 AcceptEx의 완료 맥락과 수락된 새 소켓에 나중에 제출할 수신 작업의 맥락을 구분해 두면 종료 중 잘못된 연결을 정리하는 오류를 줄일 수 있습니다.

02

득점 포인트

이해가 드러나는 지점을 확인해 보세요.

  • AcceptEx의 미리 제출하는 소켓·버퍼·중첩 I/O 계약을 설명한다.
  • 초기 수신 길이 때문에 TCP 연결과 완료가 분리될 수 있음을 짚는다.
  • SO_UPDATE_ACCEPT_CONTEXT와 GetAcceptExSockaddrs의 완료 후 절차를 정확히 말한다.
  • 취소·실패·빠른 종료에서도 다음 수락 보충과 컨텍스트 수명을 관리한다.
03

감점 포인트

놓치기 쉬운 조건과 오해를 짚어 보세요.

  • TCP 연결이 성립하면 AcceptEx가 항상 즉시 완료된다고 말한다.
  • 주소 버퍼를 임의 포인터 연산으로 해석하거나 문맥 갱신을 생략한다.
  • AcceptEx 완료를 사용자 인증이나 세션 성립으로 간주한다.
04

더 파고들 거리

하나 더 질문하며 이해의 범위를 넓혀 보세요.

득점·감점 포인트는 학습용 자기 점검 기준이며, 특정 회사의 실제 채점표가 아닙니다.

원리부터 공부하고 싶다면

답변을 보충하는 개념·예제·슈도코드를 읽어 보세요.

← 전체 질문 보기