25. 수신 Stream.Read 반환값 오처리(정상 종료·부분 수신)

난이도 하 해설 보기 →

결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커 (A)(B) 는 주목 위치 힌트다.

결함 코드 · C#
// 시나리오: 게임 서버의 세션 수신 루프. 각 메시지는 [길이 프리픽스 4바이트]
//   뒤에 [본문 bodyLen 바이트]가 오는 형식이다. 블로킹 소켓 위의
//   NetworkStream 에서 헤더와 본문을 읽어 디스패치한다.
//
// 요구사항:
//   - 상대가 연결을 정상 종료(graceful close)하면 수신 루프를 끝내고 세션을
//     정리해야 한다. 죽은 연결을 붙잡고 바쁘게 도는 일이 없어야 한다.
//   - 한 번의 Read 가 요청한 만큼 다 주지 않을 수 있다. 헤더/본문은 필요한
//     바이트가 모두 모일 때까지 읽어야 한다.
//
// 과제: Stream.Read 의 반환값을 어떻게 처리하고 있는지 (A)~(C) 지점을 보고,
//       어떤 입력/상황에서 잘못 동작하는지 진단한 뒤 수정하라.

using System;
using System.Net.Sockets;

public sealed class Session
{
    private volatile bool _running = true;
    private readonly NetworkStream _stream;
    public Session(NetworkStream s) { _stream = s; }

    public void ReceiveLoop()
    {
        var header = new byte[4];
        while (_running)
        {
            int n = _stream.Read(header, 0, 4);     // (A) 길이 프리픽스 읽기
            if (n <= 0)
                continue;                           // (A) 받은 게 없으면 다시 시도

            int bodyLen = BitConverter.ToInt32(header, 0);
            var body = new byte[bodyLen];

            int got = _stream.Read(body, 0, bodyLen); // (B) 본문 읽기

            Dispatch(body);                           // (C) 본문 처리
        }
    }

    private void Dispatch(byte[] body) { /* 패킷 핸들러로 전달 */ }
    public void Stop() => _running = false;
}
내 리뷰 · C#
내 답안 · 자동 저장

작성 후 위 해설 보기에서 모범 해설과 대조하세요.