23. 세션 객체 풀 재사용 시 상태 누수 (권한 승계 · 신원 혼동 · 패킷 오배달)

난이도 상 해설 보기 →

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

결함 코드 · C#
// ============================================================================
// [코드리뷰 문제] C# - 세션 객체 풀(object pool) 재사용 시 상태 정리
// ----------------------------------------------------------------------------
// 시나리오 (세션/접속 · 서버-클라):
//   - accept 가 잦은 서버라 매 연결마다 Session 을 새로 할당하지 않고 오브젝트 풀에서
//     빌려 쓰고(Rent), 연결이 끊기면 풀로 돌려준다(Return).
//   - Session 은 인증 여부/플레이어 식별/수신 누적 버퍼/송신 대기 큐를 들고 있다.
//   - Return 된 세션은 곧 다른 새 연결이 Rent 해서 재사용한다.
//
// 과제:
//   이 코드의 잠재적 문제를 모두 찾고, 인증된 플레이어 P 의 연결이 끊겨 세션이 풀로
//   돌아간 뒤 새 연결 Q 가 그 세션을 재사용할 때 Q 가 어떤 상태에서 시작하는지 설명하라.
//   비동기 수신/송신이 아직 끝나지 않은 채 Return 되면 무슨 일이 생기는지도 논하라.
//   수정안과 더 나은 설계를 제시하라.
//   (먼저 직접 리뷰를 적은 뒤 answer.md 와 대조할 것)
// ============================================================================

using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Net.Sockets;

public class Session
{
    public Socket Socket;
    public bool   Authenticated;          // 인증 통과 여부
    public long   PlayerId;               // 인증된 플레이어
    public int    RecvLen;                // 수신 누적 바이트 수
    public byte[] RecvBuf = new byte[4096];
    public Queue<byte[]> SendQueue = new();

    public void Init(Socket s)            // (A) 풀에서 꺼내 새 연결에 바인딩
    {
        Socket  = s;
        RecvLen = 0;
        // 그 외 필드는 이전 사용분이 그대로 남아 있다.
    }
}

public class SessionPool
{
    private readonly ConcurrentQueue<Session> _pool = new();

    public Session Rent(Socket s)
    {
        if (!_pool.TryDequeue(out var ses))
            ses = new Session();
        ses.Init(s);                      // (B)
        return ses;
    }

    public void Return(Session ses)
    {
        _pool.Enqueue(ses);               // (C) 그대로 반납
    }
}
내 리뷰 · C#
내 답안 · 자동 저장

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