20. 송신 측 부분 전송(short write)과 동시 전송으로 인한 프레임 경계 붕괴 (C#)

난이도 중 해설 보기 →

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

결함 코드 · C#
// ============================================================================
// [코드리뷰 문제] C# - 송신 측 부분 전송(short write)과 동시 전송으로 인한 프레임 경계 붕괴
// ----------------------------------------------------------------------------
// 시나리오 (프로토콜 · 서버-클라/서버-서버):
//   - 메시지는 길이 프리픽스로 프레이밍한다: 와이어 포맷 [u32 len][len 바이트 payload].
//   - Socket.Send 는 OS send() 처럼 "요청한 바이트보다 적게" 보낼 수 있고(송신 버퍼가 찼을 때),
//     실제로 보낸 바이트 수를 반환한다.
//   - 한 연결(Socket)에는 여러 스레드/소스가 메시지를 보낼 수 있다(브로드캐스트, 존 서버가
//     같은 게이트웨이 연결로 여러 플레이어 패킷을 포워딩 등).
//
// 요구사항:
//   - 한 프레임([len][payload])은 와이어에 "통째로, 끊김 없이" 나가야 한다(부분 전송 시 나머지를
//     마저 보내야 하고, 다른 메시지의 바이트가 중간에 끼면 안 된다).
//   - 길이 프리픽스의 바이트 순서(엔디안)는 송수신이 합의한 고정 포맷이어야 한다.
//   - 송신 버퍼가 차서 다 못 보낼 때(백프레셔)도 프레임이 깨지거나 유실되면 안 된다.
//
// 과제:
//   이 코드의 잠재적 문제를 모두 찾고, 왜/어떻게 수신 측에서 프레임 경계가 어긋나(메시지가
//   섞이거나 길이가 틀어져) 디싱크/오파싱이 일어나는지 설명하고, 수정안과 더 나은 설계를
//   제시하라. (먼저 직접 리뷰를 적은 뒤 answer.md 와 대조할 것)
// ============================================================================

using System;
using System.Net.Sockets;

public class MessageSender
{
    private readonly Socket _sock;

    public MessageSender(Socket sock) { _sock = sock; }

    // 길이 프리픽스 프레이밍으로 한 메시지 전송
    public void SendMessage(byte[] payload)
    {
        // (D) 길이 프리픽스의 바이트 표현(엔디안)을 검토하라
        byte[] hdr = BitConverter.GetBytes((uint)payload.Length);

        // (C) 헤더와 페이로드의 전송 방식을 검토하라
        _sock.Send(hdr, 0, 4, SocketFlags.None);                  // (A) 이 전송 호출의 반환값 처리를 검토하라
        _sock.Send(payload, 0, payload.Length, SocketFlags.None); // (A) 이 전송 호출의 반환값 처리를 검토하라

        // (B) 여러 스레드가 같은 _sock 에 동시 호출하는 경우를 검토하라
    }
}
내 리뷰 · C#
내 답안 · 자동 저장

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