47. 이벤트 루프의 연결당 무제한 드레인 (공정성 붕괴 / 기아)

난이도 상 해설 보기 →

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

결함 코드 · C#
// 시나리오: 단일 스레드 이벤트 루프(리액터) 기반 세션 처리 — C# 서버
// - 한 워커 스레드가 준비된(수신 데이터 있는) 모든 연결을 순회하며 메시지를 처리한다.
// - 대부분의 클라이언트는 초당 몇 개의 패킷만 보내지만, 일부(봇/매크로/버그 클라,
//   혹은 대량 전송 구간의 클라)는 매우 빠르게 연속 전송해 수신 큐가 급격히 쌓인다.
// - 같은 루프가 타이머·하트비트·다른 세션 처리도 담당한다(단일 스레드).
//
// 요구사항:
//   1) 한 연결이 아무리 많이 보내도 다른 연결·타이머 처리가 지나치게 지연되면 안 된다.
//   2) 처리량은 연결들 사이에 공평하게 분배되어야 한다(한 연결 독점 금지).
//
// 과제: 특정 연결이 데이터를 폭주시키면 다른 연결들의 응답이 크게 밀리거나 굶는다.
//       (A),(B) 지점을 근거로 원인과 수정안을 설명하라.

using System;
using System.Collections.Generic;

public sealed class Message { public int Seq; }

public sealed class Connection
{
    public int Id;
    public readonly Queue<Message> Inbox = new Queue<Message>();  // 소켓 수신 큐(모의)

    public bool TryReceive(out Message m)
    {
        if (Inbox.Count > 0) { m = Inbox.Dequeue(); return true; }
        m = null; return false;
    }
}

public sealed class Reactor
{
    private readonly List<Connection> _conns = new List<Connection>();
    public Action<Connection, Message> Handler = (c, m) => { };

    public void Add(Connection c) => _conns.Add(c);

    // 이벤트 루프 1회(tick). 준비된 연결을 순회한다.
    public void Tick()
    {
        foreach (var conn in _conns)                 // (A)
        {
            while (conn.TryReceive(out var msg))     // (B)
            {
                Handler(conn, msg);
            }
        }
        // 이후: 타이머/하트비트/기타 세션 유지 작업 (Tick 끝에서 수행)
    }
}
내 리뷰 · C#
내 답안 · 자동 저장

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