게임 서버 개발 관련 간단 메모

일일일일·2021년 1월 22일
0
post-thumbnail

.NET Conf 2021 x Seoul | 클라이언트 게임 개발자를 위한 소켓 프로그래밍 기초에서 활용까지

용어

MTU

Maximum Transmission Unit
1회의 데이터 전송에서 적재 가능한 IP 데이터 그램 최댓값

예시)
Ethernet 타입의 LAN 환경에서는 프레임워크가 최대 1518 byte.
이더넷 헤더(14 byte)와 FCS(4 byte)를 제외한 1500 byte가 MTU 사이즈

MTU 보다 큰 크기의 패킷을 보내면?
TCP가 알아서 분할해 보내 줌
다만 분할된 패킷들 중 하나라도 유실되면 전체를 다시 보내야 하니 주의

MSS

Maximum Segment Size
TCP가 저장하는 유저 데이터. 수신 가능한 세그먼트 사이즈의 최댓값

예시)
Ethernet 타입의 LAN 환경에서는 프레임워크가 최대 1518 byte.
이더넷 헤더(14 byte), FCS(4 byte), TCP 헤더(20 byte), IP 헤더 (20 byte)를 제외한 1460 byte가 MSS 사이즈

바이트 오더

빅 엔디언

0x1234 -> 12 34
0x12345678 -> 12 34 56 78

리틀 엔디언

0x1234 -> 34 12
0x12345678 -> 78 56 34 12

플랫폼 별 사용 바이트 오더

  • X86 CPU (Intel, AMD) : 리틀 엔디언
  • .NET : 리틀 엔디언
  • Java, Golang : 빅 엔디언

비동기

고 성능 네트워크 I/O를 위해서는 비동기 I/O가 적절하나 멀티스레드로 작동하고 분산되는 코드로 인해 개발에 어려움을 겪을 수 있다. 클라이언트 사이드에서는 고성능 I/O가 큰 성능상의 의미를 갖지 못한다. 동시 사용 소켓 수가 천 단위 이상이 되어야 비동기 I/O가 동기 I/O보다 퍼포먼스상 이득을 기대할 수 있다.

다만 메인 스레드에서 동기 I/O 소켓을 사용하면 Wait가 발생하기 때문에 네트워크 처리 스레드만 분리해 동작하는 방식을 권장한다. Queue를 사용해 스레드 동기화 최소화

패킷 관련 프레임워크

MessagePack for C#

C# 서버 - C# 클라이언트
다른 언어를 사용하는 서버와 클라이언트간에 사용 불가

유니티에서 사용

iOS 대응(Reflection 사용 불가)을 위해 AOT로 코드 제네레이션을 해 주어야 함

  • 커맨드라인으로 생성
mpc.exe -i "./EFGame.Packet.csproj" -o "MessagePackGenerated.cs"
  • 초기화 타이밍에 리졸버 코드 호출
void Start() {
	StaticCompositeResolver.Register(new IFormatterResolver[] {
     	MessagePack.Resolvers.GeneratedResolver.Instance,
        MessagePack.Resolvers.StandardResolver.Instance,
    });
    
    var resolver = StaticCompositeResolver.Instance;
    MessagePackSerializer.DefaultOptions = 
	   	MessagePackSerializerOptions.Standard.WithResolver(resolver);
}
  • 사용할 패킷 클래스
[MessagePackObject]
public class AddFriendRequestPacket {
    [Key(0)]
    public long UserID { get; set; }
    
    [Key(1)]
    public string Message { get; set; }
}

ProtoBuf

GoLang 서버 - C# 클라이언트 , C++ - C# 클라이언트 등 여러 언어의 조합으로 사용 가능

message Person {
    required string name = 1;
    required int32 id = 2;
    optional string email = 3;
}
Person john = Person.newBuilder()
    .setId(1234)
    .setName("John Doe")
    .setEmail("jdoe@example.com")
    .build();
    
output = new FileOutputStream(args[0]);
john.writeTo(output);

유니티 버전에서는 .NET STANDARD 버전을 잘 맞춰야 함

profile
무엇을 의미하는 숫자일까요?

0개의 댓글