[게임 서버] Server와 Client의 통신, 패킷(Packet) 정보 주고 받기
·
공부/게임 서버
Server에서 Client로, 또는 반대의 상황에서 정보를 주고 받는 방법을 살펴보자. Packet을 상속받는 정보들이 있다. Packet에는 모든 아이들이 반드시 가져야 할 기본 정보인 size와 packetId, Write()와 Read()를 지니고 있다. public abstract class Packet { public ushort size; public ushort packetId; public abstract ArraySegment Write(); public abstract void Read(ArraySegment s); } size는 말 그대로 정보의 크기다. packetId는 패킷을 구분해줄 장치다. Write는 패킷을 보낼 때 사용하고 Read는 패킷을 받을 때 사용한다. Player..
[게임 서버 / C# ] Socket Error (10061) : 대상 컴퓨터에서 연결을 거부했으므로 연결하지 못했습니다.
·
공부/게임 서버
혼자 서버를 만들어보던 중 이런 에러가 발생했다. 구글링해보니 방화벽을 꺼보라는데 애초에 방화벽이 꺼져있는 상태다. 멀쩡한 코드를 다운받아 실행해보니 클라이언트는 서버 내용을 받아서 잘 보여주는데 서버는 클라이언트의 내용을 받지 못하고 물론 출력도 되지 않는 상태다. 1) 클라가 보내질 못하거나, 2) 서버가 받질 못한다. 그리고 애초에 Socket Error가 발생했다. 📛 Listener에서 사용하는 sessionFactory가 null Exception이 떴다. ✅ Init의 인자로 받는 sessionFactory에 오타가 있었다... 📛 Session에 무언가 문제가 있다. 정상적이라면 클라이언트에서 보내는 데이터의 바이트 수가 12여야 하는데 내 코드로는 0이 뜬다. ✅ OnSend, SendC..
[게임 서버] 게임 해킹에 대해 알아보자
·
공부/게임 서버
게임 속에는 수많은 해커들이 있다. 개발자들은 코드 난독화, 메모리 보호 등을 이용해 해킹으로부터 게임을 보호한다. 1️⃣ 클라이언트 코드는 공개된 것과 다름 없다. 2️⃣ 클라이언트 코드/메모리는 언제나 수정할 수 있다. 즉, 서버 구조가 매우 중요하다. 서버에는 두 가지 구조가 있다. Server-based(Client-Server)와 P2P다. ✅ Client-Server 클라이언트는 모두 서버와 연결되어 있고, 서버가 그들을 관리한다. 너무 많은 요청을 한 번에 받으면 서버가 뻗을 수 있지만 보안이 좋다. ✅ P2P 서버 없이도 클라이언트끼리 서버와 클라이언트 역할을 한다. 대표적으로 테일즈런너가 이런 방식이다. 같은 게임에 있는 다른 유저의 네트워크 상황이 좋지 않으면 나까지 영향을 받게 된다...
[게임 서버/암호학] 대칭키와 비대칭키
·
공부/게임 서버
게임 서버에서 가장 중요하다고 말할 수 있는 것 중 하나가 바로 보안 문제다. 우리는 게임 내에 수많은 정보를 암호화하여 보관/관리한다. 정보를 보호할 때 암호화 키를 사용하고, 암호화된 정보를 꺼내볼 때 복호화 키를 사용한다. ✅ 대칭키 암호화/복호화 키가 같은 경우의 암호를 대킹키 암호라 한다. xor 연산을 예시로 볼 수 있다. static void Main(string[] args) { int treasure = 77; int key = 103; int secret = treasure ^ key; Console.WriteLine($"비밀 암호 : {secret}"); Console.WriteLine($"암호 해독 : {secret ^ key}"); } 우리의 소중한 정보는 77이다. 키값 103과..
[게임 서버] await 사용하기
·
공부/게임 서버
직원이 한 명 뿐인 식당이 있다. 직원은 설거지, 요리, 주문, 서빙을 모두 담당해야 한다. async도 멀티스레드가 아닌 싱글스레드에서 활용되는 경우가 있다. static async void TestAsync() { Console.WriteLine("Start TestAsync"); Task t = Task.Delay(3000); t.Wait(); Console.WriteLine("End TestAsync"); } static void Main(string[] args) { TestAsync(); Console.WriteLine("while start"); while (true) { } } 메인에서는 TestAsync()를 실행한 뒤 while start라는 문장을 프린트한다. TestAsync 안에서..
[게임 서버] SetBuffer를 RecvBuffer, SendBuffer로 따로 빼내기 #2
·
공부/게임 서버
지난 게시글에서는 RecvBuffer를 만들었다. 이번에는 SendBuffer를 만들어 따로 빼내보겠다. SendBuffer는 크게 두 클래스로 나뉜다. SendBufferHelper와 SendBuffer다. SendBufferHelper 먼저 살펴보자. // ThreadLocal == 전역은 전역 변순데 내 스레드에서만 사용할 수 있는 전역변수 public static ThreadLocal CurrentBuffer = new ThreadLocal(() => { return null; }); // 그냥 사이즈가 아니라 되게 큰 뭉탱이 Size. 여기서 필요한 만큼 뽑아다 쓸 예정. public static int ChunkSize { get; set; } = 4096 * 100; 멀티 스레드 환경에서도 ..
[게임 서버] SetBuffer를 RecvBuffer, SendBuffer로 따로 빼내기 #1
·
공부/게임 서버
패킷 단위로 데이터를 주고 받기 위해서 해야 할 첫 관문은 server 내에 있는 recvBuff를 따로 빼서 관리하는 것이다. 기존 프로그램에서는 SetBuffer를 통해 버퍼 크기, offset을 미리 설정해준 다음에 어떤 변화도 없이 쭉 그대로 사용해왔다. 이렇게 사용하게 되면 문제가 발생한다. TCP 특성상 클라이언트가 보낸 내용이 한 번에 다 오지 않을 수 있다. 앞서 보낸 데이터 중 일부가 버퍼에 데이터가 남아있을 경우 남은 데이터와 새로 보낼 데이터를 함께 보내는데 이때 매우 곤란한 상황이 펼쳐진다. 변화값인 offset을 0으로 설정했기 때문에 남은 데이터를 무시하고 그 위에 새로운 데이터를 덮어쓰게 되는 것이다. 문제를 방지하기 위해서 앞으로는 SetBuffer를 사용하지 않고 RecvB..
[게임 서버] Listener, 네트워크 연결을 기다려보자
·
공부/게임 서버
서버와 클라이언트의 연결을 기다리는 용도의 Listener 클래스는 시작점인 Init, 기다리는 연결이 바로 실행될 수 있음을 확인하는 RegisterAccept, 연결 완료를 담당하는 OnAcceptCompleted, 연결을 받아들이는 Accept 함수로 구성된다. Socket _listenSocket; Action _onAcceptHandler; // Accept가 완료됐을 때 어떻게 처리할 것인지 담당. public void Init(IPEndPoint endPoint, Action onAcceptHandler) { _listenSocket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); // AddressFami..
[게임 서버] Listener의 반대 개념, Connector에 대해서
·
공부/게임 서버
서버를 만들 때 Listener라는 이름으로 클라이언트의 연결 요청을 기다리는 클래스를 만들게 된다. 그 반대 입장으로 서버에서 서버와 클라이언트의 연결을 직접 하는 클래스를 만들어야 하는데 내가 배운 강의에서는 그 이름을 Connector라 한다. Connector를 따로 만드는 가장 큰 이유 2가지는 1️⃣ 서버 코어 안에서 클라이언트와 연결하는 일이 필요할 때 범용적으로 사용하기 위해, 2️⃣ 나중에 게임 서버를 본격적으로 만들 때 몬스터 관리, 아이템 관리 등 여러가지 서버가 생기게 되는데 이때 그 서버를 서로 연결하고자 할 때 사용하기 위해서다. Connector는 전체적으로 Listener와 흡사한 구조를 갖고 있다. Connector를 호출할 때 사용하게 되는 Connect 함수, 연결을 예..
[게임 서버] 소켓 프로그래밍 BufferList를 사용하여 한 번에 Send
·
공부/게임 서버
기존에 만든 서버에서 사용하던 send는 하나의 내용을 한 번 보내고 다음 내용이 올 때까지 대기하고, 다시 하나의 내용을 받으면 그 하나를 보내는 방식이었다. 코드로 보자면 void RegisterSend() { _pending = true; // send가 될 때까지는 sendQueue에 넣고 실제로 send가 완료됐으면 이어서 queue 확인하고 같은 작업. byte[] buff = _sendQueue.Dequeue(); // 빈 buffer가 아니고 우리가 보내는 크기에 맞는 buffer 설정 // SocketAsyncEventArgs _sendArgs = new SocketAsyncEventArgs(); _sendArgs.SetBuffer(buff, 0, buff.Length); // send를..
[게임 서버] 아주아주 간단하게 만드는 소켓 프로그래밍 환경
·
공부/게임 서버
서버와 클라이언트가 통신하기 위해서 서로 연결된 가상의 도로를 만드는데 이 도로의 양 끝을 소켓이라 부른다. 소켓 프로그래밍이란 네트워크를 통해 두 시스템이 소통하는 것을 말한다. 서버 using System; using System.Net; using System.Net.Sockets; using System.Text; namespace Server { class Program { static void Main(string[] args) { // 내 컴퓨터 IP 주소의 문자 이름을 받아오는 함수다. string host = Dns.GetHostName(); // GetHostEntry를 통해 뽑아온 host의 IP 정보, Alias 정보 등을 IPHostEntry에 담는다. IPHostEntry ipH..
[게임 서버] 파싱(Parsing)이란?
·
공부/게임 서버
파싱(Parsing)이란 문서 등의 자료에서 원하는 데이터를 뽑아온 뒤 원하는 모양으로 가공하고 필요할 때 불러오는 것을 말한다. 파싱을 담당하는 프로그램은 파서(Parser)라고 한다.
[게임 서버] DNS란?
·
공부/게임 서버
DNS는 Domain Name System의 약자다. 인터넷 주소창에 우리가 쓰는 Host Domain Name(google.com 등)을 입력했을 때 이를 컴퓨터 네트워크 장치들을 위한 번호인 IP주소로 변환해주는 시스템.
[게임 서버] TCP와 UDP
·
공부/게임 서버
TCP와 UDP는 데이터를 전송할 때 사용하는 프로토콜이다. OSI 7계층과 TCP/IP 모델의 전송계층에서 사용된다. TCP 연결형 서비스다. 전화 통화를 상상해보자. 내가 누군가와 통화를 하고 "안녕하세요? 오늘 날씨가 좋아요"라고 말한다면 듣는 사람의 입장에서도 "안녕하세요? 오늘 날씨가 좋아요"라고 같은 순서로 이야기를 전달받게 된다. TCP도 같다. 논리적 경로가 있으며, 전달 순서가 보장된다. 전달할 데이터를 분실했을 경우 자신이 책임지고 다시 데이터를 보내준다. 신뢰도가 높다. 데이터 흐름 제어, 혼잡 제어를 해준다. UDP 비연결형 서비스다. 오토바이 퀵 배달을 상상하면 쉽다. 퀵은 빠르다. 꼭 전달자가 보내는 순서대로 도착한다는 보장은 없다. UDP도 비슷하다. 연결 없이 통신이 가능하다..
[게임 서버] 오프셋(OffSet)이란?
·
공부/게임 서버
처음 주어진 요소부터의 변화값을 말한다. 예를 들어, A라는 배열 내용이 abcdef라면 c는 A 시작점에서 2만큼의 OffSet을 가진 것이다.