45. 유휴 타임아웃 판정과 활동 시각 갱신 (C#)
난이도 하 해설 보기 →
결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커
(A)(B) 는 주목 위치 힌트다.
결함 코드 · C#
// ============================================================================
// [코드리뷰 문제] C# — 유휴(idle) 타임아웃 판정과 활동 시각 갱신
// ----------------------------------------------------------------------------
// 시나리오:
// 서버는 죽은/방치된 연결을 정리하려고 세션마다 마지막 활동 시각을 기록하고,
// 주기적으로 (now - LastActivity) 가 임계(IdleTimeout)를 넘는 세션을 끊는다.
// 일부 상호작용(맵 리소스 다운로드, 대형 스냅샷 스트리밍, 상점 목록 전송)은
// 서버가 클라이언트로 오래 "보내기만" 하는 구간이 있다. 이 동안 클라이언트는
// 보낼 것이 없어 수신만 한다.
//
// 요구사항:
// - 진짜로 방치된(양방향 무통신) 연결만 유휴로 판정해 끊는다.
// - 서버가 활발히 데이터를 보내는 중인 정상 연결을 유휴로 오판해 끊으면 안 된다.
//
// 과제: (A) (B) 지점의 동작을 설명하고 수정안을 제시하라.
// ============================================================================
using System;
using System.Collections.Generic;
public sealed class Session
{
public int Id;
public DateTime LastActivity = DateTime.UtcNow;
public void OnReceive(byte[] data)
{
LastActivity = DateTime.UtcNow; // (A) 수신 시 활동 시각 갱신
// ... 수신 처리 ...
}
public void SendLargeAsset(byte[] chunk)
{
// 대형 자산을 여러 청크로 나눠 전송한다(여기서는 전송만 수행).
// ... 소켓 send ...
}
}
public sealed class IdleReaper
{
public static readonly TimeSpan IdleTimeout = TimeSpan.FromSeconds(30);
public void Sweep(IEnumerable<Session> sessions)
{
var now = DateTime.UtcNow;
foreach (var s in sessions)
{
if (now - s.LastActivity > IdleTimeout) // (B)
Disconnect(s);
}
}
private void Disconnect(Session s) { /* ... 세션 종료 ... */ }
} 결함 코드 · C++
// ============================================================================
// [코드리뷰 문제] C++ — 유휴(idle) 타임아웃 판정과 활동 시각 갱신
// ----------------------------------------------------------------------------
// 시나리오:
// 서버는 방치된 연결을 정리하려고 세션마다 마지막 활동 시각을 기록하고, 주기적으로
// (now - lastActivity) 가 임계(kIdleTimeout)를 넘는 세션을 끊는다. 일부 상호작용
// (맵 리소스 다운로드, 대형 스냅샷 스트리밍)은 서버가 클라로 오래 "보내기만" 한다.
// 이 동안 클라는 보낼 것이 없어 수신만 한다.
//
// 요구사항:
// - 진짜로 방치된(양방향 무통신) 연결만 유휴로 끊는다.
// - 서버가 활발히 전송 중인 정상 연결을 유휴로 오판해 끊으면 안 된다.
//
// 과제: (A) (B) 지점의 동작을 설명하고 수정안을 제시하라.
// ============================================================================
#include <chrono>
#include <vector>
using Clock = std::chrono::steady_clock;
struct Session {
int id = 0;
Clock::time_point lastActivity = Clock::now();
void onReceive(const unsigned char* /*data*/, size_t /*n*/) {
lastActivity = Clock::now(); // (A) 수신 시 활동 시각 갱신
// ... 수신 처리 ...
}
void sendLargeAsset(const unsigned char* /*chunk*/, size_t /*n*/) {
// 대형 자산을 청크로 나눠 전송(여기서는 전송만).
// ... 소켓 send ...
}
};
class IdleReaper {
public:
static constexpr std::chrono::seconds kIdleTimeout{30};
void sweep(std::vector<Session*>& sessions) {
auto now = Clock::now();
for (auto* s : sessions) {
if (now - s->lastActivity > kIdleTimeout) // (B)
disconnect(s);
}
}
private:
void disconnect(Session* /*s*/) { /* ... 세션 종료 ... */ }
}; 내 리뷰 · C#
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.
내 리뷰 · C++
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.