inflearn logo
강의

Course

Instructor

[C# and Unity MMORPG Game Development Series] Part 4: Game Server

Unity Integration #4

UnhandledException 으로 서버 터지는 경우

82

ahwhi

5 asked

0

안녕하세요,

해당 강의에서 만든 코드 기반으로 제 게임에 맞춘 서버를 AWS EC2에서 몇 주째 실행중입니다. 개발 컴퓨터에서 테스트할때도 그렇고 EC2에서 할때도 그렇고 강제 종료될때가 있어서 꺼지면 로그 남기게 해서 몇개 원인을 찾았는데요, UnhandledException이 뜨면서 강제종료 되는 경우가 두가지 있는 것 같습니다.

제 유추 상으로는 포트포워딩으로 게임 포트 이외에는 인바운드를 거절했는데도 쓰레기IP들이 서버를 터트리고 가는 것 같습니다.

 

첫번째.

[11-24 18:31:38] FATAL [UnhandledException] 
System.Net.Sockets.SocketException (10054): An existing connection was forcibly closed by the remote host.
   at System.Net.Sockets.Socket.UpdateStatusAfterSocketErrorAndThrowException(SocketError error, Boolean disconnectOnFailure, String callerName)
   at System.Net.Sockets.Socket.Shutdown(SocketShutdown how)
   at ServerCore.Session.Disconnect() in \Server\ServerCore\Session.cs:line 103
   at ServerCore.Session.OnRecvCompleted(Object sender, SocketAsyncEventArgs args) in \Server\ServerCore\Session.cs:line 193
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Net.Sockets.SocketAsyncEventArgs.<>c.<.cctor>b__173_0(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
   at System.Threading.ThreadPoolTypedWorkItemQueue`2.System.Threading.IThreadPoolWorkItem.Execute()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()

이 오류는 Session.cs에 소켓 Shutdown에서 발생했습니다.

public void Disconnect() {
    if (Interlocked.Exchange(ref _disconnected, 1) == 1)
        return;

    OnDisconnected(_socket.RemoteEndPoint);
    _socket.Shutdown(SocketShutdown.Both);
    _socket.Close();
    
    
    Clear();
}

서버가 터지면 안되니 임시 방편으로 try catch로 감싸놨습니다.

try {
    _socket.Shutdown(SocketShutdown.Both);
} catch (Exception e) {
    Console.WriteLine($"[NEW ADDED] SOCKET SHUTDOWN Failed {e}");
}
try {
    _socket.Close();
} catch (Exception e) {
    Console.WriteLine($"[NEW ADDED] SOCKET CLOSE Failed {e}");
}

 

두번째.

[11-25 10:16:12] FATAL [UnhandledException] 
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.Sockets.Socket'.
   at System.Net.Sockets.Socket.get_RemoteEndPoint()
   at ServerCore.Listener.OnAcceptCompleted(Object sender, SocketAsyncEventArgs args) in Server\ServerCore\Listener.cs:line 45
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Net.Sockets.SocketAsyncEventArgs.<>c.<.cctor>b__173_0(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
   at System.Threading.ThreadPoolTypedWorkItemQueue`2.System.Threading.IThreadPoolWorkItem.Execute()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()
--------------------------------------------------

이 오류는 Listener.cs의 RemoteEndPoint를 가져오는 부분에서 발생했는데요,

void OnAcceptCompleted(object sender, SocketAsyncEventArgs args) {
    if (args.SocketError == SocketError.Success) {
        Session session = _sessionFactory.Invoke();
        session.Start(args.AcceptSocket);
        session.OnConnected(args.AcceptSocket.RemoteEndPoint);
    } else
        Console.WriteLine(args.SocketError.ToString());

    RegisterAccept(args);
}

비쥬얼 스튜디오에서도 args.AcceptSocket.RemoteEndPoint 는 null일수도 있다고 뜨기는 하는데

이부분도 != null을 붙여서 해야하는지 try catch로 감싸야하는지 궁금합니다.

근본적인 원인은 예외가 왜 발생하는지 알아야하는데 전부 API 단이라 try catch 혹은 != null 빼고는 대책을 강구하기가 어렵습니다.

 

요약하자면

  1. 이런 UnhandledException이 나올때 해당 코드를 try { } catch로 해주것이 괜찮은 방법인가요?

  2. 혹시 근본적인 해결책이 있다면 궁금합니다.

C# unity 네트워크

Answer 2

0

Rookiss

와우 잘 찾으셨습니다.
강의에선 누락 되었으나 C# 네트워크 관련 함수 호출할 땐
싹 다 try-catch를 해주시는 것이 맞습니다.

M2 프로젝트에서는 저런 부분 보완 처리 코드도 추가 되었던 것으로 기억합니다.

0

ahwhi

감사합니다 ^^ 사랑합니다!!!!★

0

communityai8509

안녕하세요, 인프런 AI 인턴입니다. 아휘님께서 겪고 있는 문제는 네트워크 프로그래밍에서 종종 발생할 수 있는 연결 문제와 관련된 사항입니다. 두 가지 사례에 대해 하나씩 살펴보겠습니다.

첫 번째 오류: SocketException - “An existing connection was forcibly closed by the remote host.”

이 오류는 일반적으로 네트워크 연결이 예기치 않게 끊어진 경우에 발생합니다. 예를 들어, 클라이언트가 서버와의 연결을 강제로 닫았을 때 발생할 수 있습니다. 다음과 같은 조치를 고려할 수 있습니다:

  1. 예외 처리: 이미 시도하신 대로 try-catch로 소켓의 ShutdownClose를 감싸는 것은 올바른 접근 방식입니다. 네트워크 환경에서는 예상치 못한 오류가 발생할 수 있기 때문에 이러한 예외 처리가 필요합니다.

  2. 로그 기록: 오류 발생 시 로그를 통해 문제가 발생한 상황을 기록하여 원인을 분석하는 데 도움이 될 수 있습니다.

두 번째 오류: ObjectDisposedException - “Cannot access a disposed object.”

이 오류는 이미 해제된 소켓 객체에 접근하려 할 때 발생합니다. 이는 네트워크 비동기 작업이 완료되기 전에 소켓이 제대로 해제되지 않았을 때 생길 수 있습니다.

  1. null 체크 추가: AcceptSocketnull인지 확인한 후에 RemoteEndPoint를 접근하도록 코드를 수정할 수 있습니다.

    if (args.AcceptSocket != null && args.SocketError == SocketError.Success) {
       Session session = _sessionFactory.Invoke();
       session.Start(args.AcceptSocket);
       if (args.AcceptSocket.RemoteEndPoint != null) {
           session.OnConnected(args.AcceptSocket.RemoteEndPoint);
       }
    }
    
  2. 코드 흐름 점검: 연결 수립과 소켓 상태 관리를 철저히 점검하여 비동기 작업 중 소켓 객체가 폐기되지 않는지 확인하는 것이 중요합니다.

전반적인 조언

  • 예외 처리 관행: 각 네트워크 작업에 대해 예외 처리를 도입하는 것은 네트워크 프로그래밍에서 필수적입니다. 예외 처리를 통해 프로그램이 비정상 종료되지 않도록 관리할 수 있습니다.

  • 근본적인 해결책: 근본적인 해결책을 찾기 위해서는 네트워크 흐름의 모든 단계에서 문제를 파악하고 처리할 수 있는 예외를 정의하는 것이 중요합니다. 또한, 네트워크 보안을 강화하고 외부 비정상 트래픽을 차단하는 장치를 사용해 보실 것을 권장합니다.

관련된 유사한 질문과 답변은 다음 링크에서 확인하실 수 있습니다:
- “프로그램 에러 관련 질문…”

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

TLS 질문드립니다.

0

34

2

SpinLock과 컨텍스트스위칭에 대해 질문 남겨요.

0

39

2

Unity Span

0

65

2

XML, Dll 차이점

0

99

2

Session 질문입니다

0

74

1

Write Read 커서 키워드

0

69

1

더미 클라이언트 수에 따른 OnDisconnect 발생

0

65

2

네트워크 Send 전담 스레드 배치

0

94

2

컨텐츠 단, 엔진 단

0

100

1

질문 있습니다

0

73

2

C# 게임서버 3D MMORPG

0

141

2

유니티6 버전

0

94

2

receive하는 부분과 send하는 부분의 차이

0

128

2

커서의 위치의 중요성

0

99

2

C++ 전혀 모르는데 C# 서버

0

164

2

강의에 질문이 있습니다

0

83

2

멀티스레드 이해도 질문

0

90

1

500 vs 500

0

122

3

OnAcceptHandler 액션 함수

0

57

1

이 정도 서버의 객관적인 수준이 궁금합니다.

0

185

2

36. Serialization #3 에서 string (name) 코드 수정 질문

0

78

2

외부 컴퓨터와의 통신 방법이 궁금합니다

0

100

1

스핀락 질문.

0

104

2

안녕하세요 취업 학원 관련해서 문의드립니다.

0

174

2