30. 비동기 송신 버퍼의 조기 반납: in-flight 중 재사용 (C#)

난이도 중 해설 보기 →

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

결함 코드 · C#
// [시나리오] 비동기 송신에서 풀 버퍼의 수명 (서버-클라)
// 고빈도 송신을 위해 송신 버퍼를 ArrayPool 에서 빌려 쓴다.
// 메시지를 버퍼에 복사한 뒤 비동기 송신(BeginSend)을 시작하고,
// 전송이 끝나면 완료 콜백(OnSent)에서 마무리한다.
// 한 연결에는 여러 게임 로직 스레드가 브로드캐스트/개별 통지를 보낼 수 있다.
//
// [요구사항]
//   - 각 클라이언트는 자신에게 보낸 바이트를 정확히(온전하게) 받아야 한다.
//   - 다른 연결로 보낼 데이터가 섞이거나 새어 나가면 안 된다.
//
// [과제] Connection.Send 를 검토하고, 송신이 잦거나 여러 스레드가 같은 연결로
//        동시에 보낼 때 무엇이 잘못될 수 있는지 원인과 수정안을 제시하라.
//        표시된 (A)(B) 지점에 주목하라.

using System;
using System.Buffers;
using System.Net.Sockets;

class Connection
{
    private readonly Socket _socket;
    public Connection(Socket s) { _socket = s; }

    // 여러 스레드에서 호출되어 이 연결로 메시지를 보낸다.
    public void Send(byte[] message, int len)
    {
        byte[] buf = ArrayPool<byte>.Shared.Rent(len);       // 풀에서 대여
        Buffer.BlockCopy(message, 0, buf, 0, len);

        // (A)
        _socket.BeginSend(buf, 0, len, SocketFlags.None, OnSent, buf);

        // (B)
        ArrayPool<byte>.Shared.Return(buf);
    }

    private void OnSent(IAsyncResult ar)
    {
        int sent = _socket.EndSend(ar);
        // 송신 완료 처리
    }
}
내 리뷰 · C#
내 답안 · 자동 저장

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