반응형

 

짧은 영어로 번역하는것이라 오역, 의역이 있을수 있습니다.

좀더 정확한 정보를 얻거나 실력을 향상시키실 분들은 해당 블로그에 직접 가셔서 여러번 읽어보시길 바랍니다.

 

 

출처  : https://gafferongames.com/post/sending_and_receiving_packets/

 

Sending and Receiving Packets | Gaffer On Games

Introduction Hi, I’m Glenn Fiedler and welcome to Networking for Game Programmers. In the previous article we discussed options for sending data between computers and decided to use UDP instead of TCP for time critical data. In this article I am going to s

gafferongames.com

 

BSD 소켓

당신이 지닌 일종의 BSD소켓들에 기반한 사용 가능한 기본소켓 레이어 현대 플랫폼에 대해서 

 

BSD 소켓들은 "socket", "Bind", "SendTo" 그리고 "RecvFrom"같은 간단한 함수를 통해 다뤄진다.

물론 너가 원한다면 해당 함수들을 직접 사용할 수 있지만,

이것은 각 플랫폼들이 약간씩 다르기 때문에 플랫폼 독립적인 코드로 유지하기란 어려운 일이다.

 

그렇기 때문에 내가 최초로 당신에게 기본 소켓의 사용을 설명하기 위해 BSD 소켓 예제코드를 보여줬을 지라도,

우리는 BSD 소켓들을 직접 사용하진 않을 것이다.

우선 우리는 우리가 모든 방법으로 추상화 할 수 있는 클래스들의 모음의 모든 소켓기능을 다루고 있다.

이것은 우리가 플랫폼 독립적인 코드를 쓰는 것을 좀더 쉽게 만들어 줄 것이다.

 

 

플랫폼 사양

 

우선 정의를 설정하자 그러면 우리는 현재 우리의 플랫폼이 무엇인지 탐지할 수 있고,

소켓들이 다른 플랫폼으로부터 약간의 다른점을 다룰 수 있다.

 

    // platform detection

    #define PLATFORM_WINDOWS  1
    #define PLATFORM_MAC      2
    #define PLATFORM_UNIX     3

    #if defined(_WIN32)
    #define PLATFORM PLATFORM_WINDOWS
    #elif defined(__APPLE__)
    #define PLATFORM PLATFORM_MAC
    #else
    #define PLATFORM PLATFORM_UNIX
    #endif

 

이제 소켓에 적당한 헤더를 include 해보자.

플랫폼 사양에 맞는 헤더파일들이기 때문에, 우리는 그 플랫폼에 맞는 다른 파일셋들을 include할 수 있다.

#if PLATFORM == PLATFORM_WINDOWS

        #include <winsock2.h>

    #elif PLATFORM == PLATFORM_MAC || 
          PLATFORM == PLATFORM_UNIX

        #include <sys/socket.h>
        #include <netinet/in.h>
        #include <fcntl.h>

    #endif

 

 

반응형
Posted by Sweetmeats_boy
반응형

출처 : https://www.redblobgames.com/grids/hexagons/#coordinates

 

Red Blob Games: Hexagonal Grids

Guide to math, algorithms, and code for hexagonal grids in games

www.redblobgames.com

 

좌표 체계

 

Now let's assemble hexagons into a grid. With square grid, there's one obvious way do it.

with hexagons, there are multiple approaches.

I like cube coordinates for algorithms and axial or doudbled for storage.

 

Offset coordinates

The most common approach is to offset every other column or row. Columns are named col (q). Rows are named row (r). You can either offset the odd or the even column/rows, so the horizontal and vertical hexagons each have two variants.

 

- 지금부터 사각 격자안에 헥사곤을 모아보자. 거기에는 분명한 방법이 있다.

헥사곤에 관해서, 여러가지 접근방식이 있다.

나는 큐브 좌표를 위한 알고리즘들과 축 또는 두개의 저장방식(?)을 좋아한다.

 

오프셋 좌표

=> 오프셋 뜻은 여러가지가 있지만 여기서는 '상대주소 지정방식'이라는 의미로 사용된듯 하다.

 

가장 일반적인 접근방식은 모든 열 또는 행을 offset으로 만드는 것이다.

열은 col(q), 행은 row(r) 이라고 칭한다.

당신은 어느 한쪽의 홀수 또는 짝수 offset으로 된 행,열을 구성 할 수 있으며,

또한 수직 그리고 수평 헥사곤으로 두가지의 다른 방법이 있다.

 

 

 

반응형
Posted by Sweetmeats_boy
반응형

출처 : https://www.redblobgames.com/grids/hexagons/

 

Red Blob Games: Hexagonal Grids

Guide to math, algorithms, and code for hexagonal grids in games

www.redblobgames.com

위 싸이트에는 게임과 관련된 알고리즘 등도 많고 마우스와 상호작용하는 방식으로 예시를 볼 수 있기 때문에 한번쯤 구경하면 좋다.

 

우선 번역할 내용은 육각타일맵과 관련된 내용으로 일반적인 사각형 타일맵과는 여러모로 규칙이 다르다.

 

This guide will cover various ways to make hexagonal grids, the relationships between different approaches, and common formulas and algorithms. Hexagonal grids aren't as common as square grids. I've been collecting hex grid resources for over 20 years, and wrote this guide to the most elegant approaches that lead to the simplest code, largely based on the guides by Charles Fu and Clark Verbrugge. Most parts of this page are interactive.

 

-이 가이드는 다양한 방법의 육각형 그리드를 만드는 방법, 다른 접근방법, 일반적인 공식과 알고리즘 등에 대해서 기술할 것이다.

육각 그리드는 일반적인 사각 그리드와는 같지 않다.

나는 근 20년동안 육각 그리드에 대한 자료를 모아왔고, 그에 대한 가장 간단한 코드를 만들기 위한 가장 우아한 가이드이며, 'Charles Fu'와 'Clark verbrugge'의 가이드를 가장 많이 참고했다.

대부분 이 웹 페이지는 상호작용을 한다.

 

The code samples on this page are written in pseudo-code; they're meant to be easy to read and understand. The implementation guide has code in C++, Javascript, C#, Python, Java, Typescript, and more.

 

- 이 페이지에 있는 코드 샘플은 대부분 스도코드로 작성됐고, 이것은 읽고 이해하기 쉽게 하기 위해서이다.

이 구성 가이드는 c++, c#, 자바스크립트 등의 코드로 구현되어 있다.

 

Hexagons are 6-sided polygons. Regular hexagons have all the sides the same length. I'll assume all the hexagons we're working with here are regular. The typical orientations for hex grids are vertical columns (flat topped) and horizontal rows (pointy topped).

 

- 핵사곤은 6개의 변을 지닌 폴리곤이다. 규칙적인 헥사곤은 모든 변이 같은 길이를 지닌다.

나는 우리가 여기서 작업할 모든 헥사곤은 규칙적이라고 가정한다.

육각형을 배치하는 경우에 따라서 수직, 수평으로 구분된다. [수직 : 변이 밑에 있는 형태 / 수평 : 점이 밑에 있는 형태]

 

Angles

 

In a regular hexagon the interior angles are 120°. There are six “wedges”, each an equilateral triangle with 60° angles inside. Each corner is size units away from the center. In code: function flat_hex_corner(center, size, i);

 

- 규칙적인 헥사곤은 내부각도가 120도이다. 총 6개의 "웨지", 각각의 내각이 60도인 등변 삼각형이 내부에 있다.

각 꼭지점은 중심에서 중심으로부터 떨어진 크기단위이다[?]

* 코드는 해당 싸이트에서 확인 할것.

 

To fill a hexagon, gather the polygon vertices at hex_corner(…, 0) through hex_corner(…, 5). To draw a hexagon outline, use those vertices, and then draw a line back to hex_corner(…, 0).

 

- 헥사곤을 채우기 위해서, 각 폴리곤의 정점을 i에 0 ~ 5 를 통해서 얻을 수 있다.

헥사곤 외곽선을 그리기 위해서, 이 정점들을 둘러서 그리면 된다.

 

The difference between the two orientations is a rotation, and that causes the angles to change: flat topped angles are 0°, 60°, 120°, 180°, 240°, 300° and pointy topped angles are 30°, 90°, 150°, 210°, 270°, 330°. Note that the diagrams on this page use the y axis pointing down (angles increase clockwise); you may have to make some adjustments if your y axis points up (angles increase counterclockwise).

 

- 두가지 방향배치 방법 사이에는 회전으로 인한 각도의 차이가 생긴다.

[플랫탑] 방식은 0도에서 60, 120 ..., 300도이며 [포인트]탑 방식은 30도에서 90, 150 ..., 330도이다.

이 페이지에 있는 해당 다이어그램이 y축값이 음수인 포인트들은 시계방향으로 각도가 커진다는 것을 알아두자.

당신은 y축값이 양수인 포인트들은 별도의 정의가 필요할 수 있다.

 

Size and Spacing

Next we want to put serveral hexagons together.

In the pointy orientation, a hexagon has width 'w=sqrt(3)* size' and height 'h=2*size'

The sqrt(3) comes from sin60

 

- 다음으로 우리는 여러 헥사곤들을 놓을 것이다.

'point top'방식으로 된 헥사곤은 가로는 sqrt(3)* 변의 길이, 높이는 2*변의 길이가 된다.

이때 sqrt(3)의 경우 sin60에서 도출한 것이다.

=> flat top 방식의 경우 w = 2*size, h = sqrt(3)*size가 된다.

 

The horizontal distance between adjacent hexagon centers is 'w'

The vertical distance between adjacent hexagon centers is h*3/4.

 

- 인접한 헥사곤 중심의 수평 거리는 w이며 인접한 헥사곤 중심의 수직거리는 h*3/4이다.

=> 'flat top'방식의 경우 수평거리는 w*3/4, 수직거리는 h이다.

=> 출처 싸이트에서 이미지 확인하면 이해하기 쉬움.

 

 

some games use pixel art for hexagons that does not match an exactly regular polygon.

The angles and spacing formulas I describe in this section won't match the sizes of your hexagons.

the rest of the article, describing algorithms on hex grids, will work even if your hexagons are stretched or shrunk a bit, and I explain on the implementation page how to handle stretching.

 

- 몆몆 게임은 정확히 규격화되지 않은 헥사곤을 픽셀아트 측면에서 사용한다

내가 이 섹션에서 서술한 각도와 공간 식은 너의 헥사곤과 같지 않을 수 있다.

기사의 남은 부분들은, 헥사 그리드에서의 알고리즘에 관해서 서술하고 있고, 이것은 늘어나거나 줄어든 너의 헥사곤에서도 작동할 것이다.

그리고 나는 구현 페이지에서 어떻게 늘리는 방법에 대해서도 설명한다.

 

 

반응형
Posted by Sweetmeats_boy
반응형

짧은 영어로 번역하는것이라 오역, 의역이 있을수 있습니다.

좀더 정확한 정보를 얻거나 실력을 향상시키실 분들은 해당 블로그에 직접 가셔서 여러번 읽어보시길 바랍니다.

 

 

출처 : https://towardsdatascience.com/10-common-software-architectural-patterns-in-a-nutshell-a0b47a1e9013

 

10 Common Software Architectural Patterns in a nutshell

Ever wondered how large enterprise scale systems are designed? Before major software development starts, we have to choose a suitable…

towardsdatascience.com

출처 2 : https://mingrammer.com/translation-10-common-software-architectural-patterns-in-a-nutshell/

-> 다른분이 번역한 포스팅

 

큰 규모의 시스템을 어떻게 디자인 하는지에 대해서 궁금해 본적이 있는가?

주요 소프트웨어 개발을 시작하기 전에,

우리가 원하는 기능성과 품질 요소를 제공할 수 있는 구조를 선택해서 적용해야 한다.

그렇기 때문에, 우리는 그것들을 적용하기 전에 각기 다른 설계구조에 대해서 이해를 해야 한다.

 

설계 패턴(architectural Pattern)이란 무엇인가?

위키에 따르면 아래와 같다.

- 설계 패턴이란 일반적으로, 소프트웨어 구조 안의 주어진 문맥속에서 일반적으로 발생하는 문제들에서

다시 사용할 수 있는 패턴들을 뜻한다.

 => 유형화된 해결책들.

 

이 포스팅에서, 난 아래의 각각의 사용처와 장점을 지닌 10가지 설계구조를 설명할 수 있을것이라고 믿는다.

각 패턴들의 이름은 아래와 같다.

1. 계층화 패턴 [Layered pattern]

2. 클라이언트 - 서버 패턴 [Client-Server pattern]

3. 마스터 - 스렐이브 패턴 [Master-slave pattern]

4. 파이프 - 필터 패턴 [pipe-filter pattern]

5. 브로커 패턴 [Broker pattern]

6. 피어 투 피어 패턴 [Peer-to-peer pattern]

7. 이벤트 버스 패턴 [Event-bus pattern]

8. MVC 패턴 [Model-View-Controller pattern]

9. 블랙 보드 패턴 [Blackboard pattern]

10. 인터프리터 패턴 [Interpreter pattern]

 

 

1. 계층화 패턴

 

이 패턴은 프로그램들의 구조를 서브 Task,각각의 구분된 추상화 레벨들로부터 프로그램을 구분시켜주는 구조이다.

각 계층은 자신의 상위 계층에 서비스를 제공한다.

ex : IOS의 Layer Structure 이미지

 

ex : 블루투스의 Protocol Stack Layer

 

가장 일반적으로 찾을 수 있는 시스템에서 사용하는 4계층은 아래와 같다.

1. Presentation Layer (또는 UI Layer로 알려짐)

2. Application Layer (또는 Service Layer로 알려짐)

3. Buiseness Layer (또는 Domain Layer로 알려짐)

4. Data Access Layer (또는 Persistence Layer로 알려짐)

 

계층화 패턴은 일반적인 PC 프로그램 혹은 웹 프로그램에서 주로 사용된다.

 

 

2. Client - Server Pattern 

이 패턴은 주로 두개의 부분으로 구분 할 수 있는 한개의 서버와 다수의 클라이언트로 구성된다. 

서버는 다수의 클라이언트들에게 서비스를 제공한다.

클라이언트는 서버로부터 서비스를 요청하며, 서버는 관련된 서비스를 해당 크라이언트에게 제공한다.

나아가서 서버는 계속 클라이언트의 요청이 있는지 확인한다.

 

Server - Client 패턴은 Email, 웹 공유 문서 혹은 은행서비스 등의 프로그램에 쓰인다.

 

 

3.  Master - Slave pattern 

이 패턴은 두개의 부분으로 구성된다. 바로 마스터와 슬레이브이다.

마스터는 각각의 슬레이브들(100% 동일한)에게 작업을 분할한다.

그리고 슬레이브는 계산된 최종 결과를 마스터에게 반환한다.

 

Master-Slave 패턴은 DB 복제에서, 신뢰할 수 있는 마스터 DB, 그리고 그 마스터 DB와 동기화된 슬레이브 DB

에서 사용되며 컴퓨터 시스템에서 bus에 연결된 주변장치 등에서 사용된다.

-> master drive 와 slave drive

 

4. Pipe - Filter Pattern

이 패턴은 Data의 Stream을 처리하고 진행하는 구조에서 사용될 수 있다.

각각의 진행 단계는 내부에 Filter 구성을 감싸고 있다.

데이터는 Pipe를 지날 때 특정 처리단계를 거치게 되며,해당 pipe는 지연처리 혹은 동기화를 목적으로 사용 될 수 있다.

 

Pipe-Filter 패턴은 Compiler, 연속적으로 어휘 분석, 변경, 의미 분석 그리고 code 생성을 수행하는 필터에 사용된다.

 

 

5. Broker Pattern 

이 패턴은 분리된 분산시스템에 사용되는 구조이다. 이 구성들은 각각 다른 원격 서비스 호출에 상호작용을 할수 있다.

브로커는 동등한 구성요소들간의 통신을 조정하는 역할을한다.

 

서버들은 서버들의 능력(서비스와 특징)을 브로커에게 전파(publish)한다.

클라이언트들은 브로커에게 요청하고, 브로커는 해당 클라이언트에 적용할 수 있는 

레지스트리에 등록된 서비스로 redirect한다.

 

이 패턴은 Apache ActiveMQ, Apache Kafka, RabbitMQ, JBossMessaging 같은 메세지 브로커 프로그램에서 사용된다.

 

 

6. Peer-To-Peer Pattern 

이 패턴에서는 개개의 구성품들을 Peer라고 한다.

피어들은 기능적으로는 클라이언트이며 다른 피어들로부터 요청을 받는측면에서는 서버라고 할 수 있다.

피어는 서버 혹은 클라이언트처럼 행동할 수 있고 이것은 그때그때 역할이 바뀐다.

 

Peer-To-Peer 패턴은 네트워크 파일 공유 시스템(Gnutella or G2), 멀티미디어 프로토콜(P2PTV, PDTP)에 사용된다.

 

 

7. Event-bus-pattern 

이 패턴은 주로 이벤트를 다루며 4개의 주요 구성품을 갖는다.

4개의 주요 구성으로는 이벤트 소스, 이벤트 리스너, 채널, 그리고 이벤트 버스가 있다.

이벤트 소스는 메세지를 이벤트 버스에 속한 개개의 채널에 알리고 이벤트 리스너는 개개의 채널에 대해서 구독을 한다.

리스너는 이전에 구독한 채널을 통해서 전파되는 메세지를 알아차릴 수 있다.

 

Event-bus-pattern은 안드로이드 개발 및 Noti 서비스에 사용된다.

 

 

 

8. Model-View-Controller Pattern

MVC 패턴으로도 알려진 이 패턴은 프로그램의 상호작용을 3가지 부분으로 나눈 것이다.

Model : 핵심적인 기능, data를 포함한다.

View : 정보를 유저에게 보여준다.(여러개의 View가 존재할 수 있다.)

Controller : 유저로부터의 입력을 다룬다.

 

이것은 정보가 사용자에게 제공되는 방식과 사용자로부터 받아들여지는 방식에서  정보의 내부적인 표현을 분리하기 위해서 나뉘어진다. 이는 각 구성품들을 분리하며, 코드의 효율적인 재사용을 가능하게 한다.

 

주요 프로그래밍 언어에서 WWW어플리케이션 구조에 사용한다.

(Redis 그리고 Django등등)

 

 

9. Blackboard Pattern 

이 패턴은 해결책이 알려지지 않은 문제를 해결하는데 유용합니다.

Blackboard Pattern은 3가지로 구성되어 있습니다.

 

Blackboard : 솔루션 공간안의 오브젝트들을 포함하는 구조화된 전역 메모리

Knoledge source : 자체 표현에 특화된 모듈

control component : 선택, 구성과 실행 모듈

 

모든 구성들은 Balckboard에 접근해야 한다.

구성들은 Blackboard에 추가될 새로운 Data객체들을 생성할지도 모른다.

구성들은 Blackboard상의 특별한 종류의 Data를 찾고,

Knoledge source에 존재하는 패턴과 매치되는 해당 Data를 찾을 수 있다.

 

 Blackboard pattern은 주로 음성인식, 차량 식별과 추적, 단백질 구조 식별, 수중음파 해석등에 사용된다.

 

 

10. interpret pattern 

이 패턴은 특정한 언어에 대한 통역 프로그램의 구성품을 디자인할 때 사용된다.

이것은 주로 어떻게 프로그램의 줄들, 특정한 언어로 쓰여진 문장 혹은 표현식을 어떻게 평가할지 지정한다

기본적인 개념은 언어의 각 표식에 따라 계층을 만드는 것이다.

 

 

PS : Component를 구성 혹은 구성품이라고 번역해봤는데 뭔가 적절한 번역을 못찾겠음

반응형
Posted by Sweetmeats_boy
반응형
짧은 영어로 번역하는것이라 오역, 의역이 있을수 있습니다.

좀더 정확한 정보를 얻거나 실력을 향상시키실 분들은 해당 블로그에 직접 가셔서 여러번 읽어보시길 바랍니다.



출처 : GAFFER ON GAMES

 - http://gafferongames.com/networking-for-game-programmers/udp-vs-tcp/




TCP / IP

TCP는 'Transmission Control Protocol'이며 IP는 'Internet Protocol'입니다,

위의 두개는 당신이 온라인에서하는 모든 것, 웹 브라우저에서 email을 사용하기 위한 IRC의 기반이 되며 이 모든 것들은 TCP/IP 위에 지어졌습니다.


만약 당신이 TCP 소켓을 사용한 적이 있다면 당신은 이것이 신뢰할 수 있는 연결 기반의 Protocol 이라는 것을 알수 있다. 이것은 단순히 두 장치 사이에 연결을 만들고 두 컴퓨터 간의 데이터를 전송하는 것이 한쪽에서는 파일을 쓰고 다른 한쪽에서는 파일을 읽는 것과 매우 흡사하다는 것을 의미합니다.


이 접속은 신뢰할수 있고 정렬되어 있습니다. 

당신이 보낸 모든 데이터는 다른쪽에 도착할 때 당신이 작성한 순서대로 도착하는 것을 보장할 수 있습니다.

이것은 또한 data의 Stream이며 TCP가 주의해서 당신의 데이터를 패킷으로 분할하고 네트워크를 통해 당신에게 보낼수 있도록 합니다.


다시 말하지만 이것은 파일 입출력과 비슷하다는 것을 잊지마세요. 간단합니다!



IP


단순성은 TCP 밑의 저수준의 IP 프로토콜에서 일어나는 일과는 뚜렷한 차이가 있습니다.


여기에는 연결에 대한 개념은 없습니다, 대신 다음 목적지를 향해 한 컴퓨터를 지나가는 패킷이 있습니다.

이것은 사람이 많은 방에서 쪽지를 다른 한사람에게 전달해주는 것으로 볼 수 있습니다.


이것은 해당 사람에게 전달된다는 것을 보장하지 않습니다.

보낸사람은 그저 그 쪽지가 전달되는것을 희망하는것이 최선입니다.

[보낸사람은 그저 쪽지가 전달되기를 바랄 뿐입니다.]

해당 쪽지를 받았는지 아닌지는 절대 알수 없습니다, 다른사람이 답장을 쓰지 않는한 말이죠



물론 현실에서는 위에서 말한것보단 좀더 복잡하게 이루어집니다.

물론 어떠한 컴퓨터도 컴퓨터들을 지나 패킷들이 목적지까지 가장 빠르게 도달하는 정확한 전송과정을 알고있지 못하기 때문입니다.


때때로 'IP는 여러개의 복사된 패킷들에 따라서, 그 패킷들은 목적지까지 다다르는 여러 경로

를 만들어 냅니다., 그래서 제각각 도착시간이 다를수 있습니다.



이것은 인터넷이 스스로 형성되고 스스로 복구되도록 디자인되었기 때문이며 

접속문제가 생겨도 주변을 통해 접근할 수 있도록 하기 위해서입니다.

[위 문장 거의 의역]


당신이 실제로 어떻게 도달해야하는지에 대한 낮은 레벨에 대해서 어떻게 진행되는지 생각해보는것도 확실히 멋진 일이다. 당신은 이 내용을 TCP/IP illustrated 책에서 읽을 수 있다.



UDP


두 컴퓨터 사이의 소통을 마치 파일을 쓰는 것처럼 다루는 대신에,우리가 패킷들을 직접 보내고 받는건 어떨까?


우리는 이것을 UDP를 사용함으로써 할 수 있다.

UDP는 유저 데이터그램 프로토콜에 기반하고 이것은 TCP처럼 IP위에서 구현되는 또다른 프로토콜이다. 그러나 이번에는 복잡성과 여러 특징들을 대신 그저 IP위에 매우 얇은 계층을 더할 뿐입니다.


UDP를 통해서 우리는 패킷을 목표IP주소와 port로 보낼수 있습니다.

그리고 이것은 목적지를 향해서 컴퓨터에서 컴퓨터를 통해 도달하거나 혹은 이 과정중에 유실될 수 있습니다.


수신자 측에서, 우리는 단지 특정 포트를 통해 기다릴수 있으며[listen] 

익명의 컴퓨터로부터 패킷이 도착했을 때, 우리는 그제서야 패킷을 보낸측의 주소와 port를 알 수 있다.

[위 내용은 UDP는 실제 컴퓨터간의 연결을 통한 전송이아니라 목적지만 정하고 전달하는 특징 때문]


UDP는 순서를 유지해주지 않는 프로토콜이다. 

실제로 대부분의 전송된 패킷은 실제 전송한 것에 비해서 1~5%센트가 유실된다.

그리고 경우에 따라서 모든 패킷을 못받는 시기가 올 수 도 있다.

[당신과 당신이 원하는 목적지 사이에 수많은 컴퓨터들이 있기때문에 잘못 전달될 수 있다는 것을 명심해라]



그리고 UDP는 패킷의 순서를 보장해주지 않는다.

만약 5개의 패킷을 보냈다면 이것들은 3,1,2,4,5 순서로 도착할 수도 있다.

실제로 패킷들은 대부분의 경우에는 순서대로 도착한다.

다만 보장할 수 없다는 것이다.

[왠만하면 순서대로 오지만 결국 확인을 해야된다는 말]



마지막으로, 대부분의 UDP는 IP프로토콜의 위에 많은것을 추가하지 않았지만,

이것은 단 한가지를 당신에게 보장한다.

만약 당신이 패킷을 보냈다면, 이것은 보낸패킷들이 전부다 도착하거나 전부다 도착하지 않는다는 것이다.

따라서 만약 당신이 256바이트의 패킷을 다른 컴퓨터로 보냈다면, 그 컴퓨터는 100바이트만 수신하지 않고 256바이트의 모든 데이터를 받는다.


이것이 UDP가 당신에게 보장하는 단 한가지이다.



TCP와 UDP


우리는 TCP와 UDP 사이에서 어떤 것을 사용할 지 결정을 해야한다.

각각의 특징을 알아보자.


TCP

 - 접속기반 프로토콜

 - 순서와 신뢰성을 보장한다.

-> 여기서의 신뢰성은 보낸 메세지가 유실되지 않는다는 것.

 - 당신을 위해서 패킷에 저장된 data를 끊어준다.

 - 이것은 내부연결을 핸들링하여 보내려는 데이터가 너무 빨리 전송되지 않도록 합니다.

 - 사용하기에 쉽습니다, 당신은 그저 파일을 읅거나 쓰는것과 같은 작업을 하면 됩니다.



UDP

 - 연결[혹은 접속]이라는 개념이 없으며, 당신 스스로 이것에 대한 처리를 코드를 작성합으로써 처리해야 합니다.

 - 패킷의 순서 혹은 신뢰성을 보장하지 않습니다. 패킷들은 무작위 순서로 도착하거나, 중복되거나, 혹은 모든 패킷들이 다 도착하지 않을 수 있습니다.

 - 당신은 당신의 데이터를 잘라 패킷에 넣고 그것들을 보내야합니다.

 - 당신은 데이터가 인터넷연결보다 빠르게 전송되지 않도록 다뤄야 할 필요가 있습니다..

 - 만약 패킷이 유실되었다면, 당신은 이것을 알아 채고 필요하다면 데이터를 다시 전송할 방법이 필요합니다.


결정은 꽤 간단해보입니다, UDP는 우리가 모든 코드를 작성해서 고통을 받는 동안 TCP는 우리가 사용하기 쉽습니다.

그렇다면 우리는 바로 TCP를 선택해야 할까요?


틀렸습니다.


TCP를 사용하는 것은 최악의 경우 FPS같은 게임을 개발할 때 실수를 일으킬 수 있습니다.

왜 그런지 생각해봅시다. 당신은 TCP가 실제로 IP위에서 모든것을 간단하게 작업하는지에 대해서 살펴봐야 할 필요가 있습니다.



그렇다면 TCP는 실제 어떻게 작동하는가?

TCP와 UDP는 모두 IP를 기반으로 만들어 졌습니다.

그러나 둘은 근복적으로 차이점이 있습니다. UDP는 밑에있는 IP와 매우 흡사하게 행동합니다.

TCP는 파일 입출력처럼 느끼도록 모든것을 추상화하여 당신에게 패킷의 복잡성과 비신뢰성을 모두 숨김니다.


그렇다면 이것은 어떻게 이루어 지는가?


우선, TCP는 스트림기반의 프로토콜입니다.

따라서 당신은 그저 바이트 스트림을 작성하면 되며, TCP는 해당 스트림이 반대편까지 가로질러 가는것을 보장합니다.

IP는 패킷기반이며, TCP는 이 IP 위세 구축되었고, 그러므로 TCP는 반드시 당신의 데이터스트림을 패킷안에 잘라 넣어야 합니다.

이제 당신이 보내려는 데이터를 TCP는 코드 내부의 대기열에 넣습니다, 그러면 대기열에 데이터가 충분히 모였을 때 TCP는 패킷을 다른 장치에 전송합니다.


이것은 멀티플레이 게임에서 문제를 일으킬 수 있습니다.

만약 당신이 매우 작은 패킷을 보냈다면, TCP는 충분한 양의 데이터가 모이지 않았다고 판단하는 일이 발생할 수 있습니다.

이게 왜 문제냐면, 당신은 클라이언트에게서 입력정보를 가능하면 빨리 얻고 싶을것이기 때문입니다.

만약 TCP가 작을 패킷을 처리하는 것때문에 딜레이되거나 "엉망이 된다면", 클라이언트 유저는 게임이 거지같다고 느낄것입니다.

게임 네트워크는 주기적인 대신 우리가 원하는것처럼 빈번하게 수신되어야 합니다


TCP는 TCP_NODELAY라는 옵션을 지정할 수 있습니다.

이 옵션은 TCP가 충분한 데이터가 모이지 않더라도 당신이 데이터를 작성한 그 즉시, 

더 기다리지 않고 전송하도록 합니다.

이것은 경우에 따라서 Nagle 알고리즘을 사용하지 않는 방법으로 제공됩니다.


불행히도, 만약 당신이 이 옵션을 사용한다고 해도, TCP는 멀티플레이어 네트워크 게임에 사용하기에는 매우 중대한 문제점을 지니고 있습니다.


이 모든것은 TCP가 신뢰성과 순차성같은 환상을 당신에게 보여주기 위해서 어떠한 방법으로 손상되거나 순서가 없는 패킷들을 다루는지에서 시작됩니다.



실제로 TCP는 어떻게 구현되어 있을까?


기본적으로 TCP는 패킷안에 데이터를 자르고, 이 패킷을 IP를 통해 신뢰성 없이 전송한다.

그러면 반대편에서 이 패킷을 수신 후 스트림으로 재구성한다.


그렇다면 패킷이 유실되었을때는 어떤일이 일어나는가?

패킷이 순서 없이 도착하거나 망가지면 어떠한 일이 일어나는가??


어떻게 TCP가 작동하는지에 대해 깊게 들어가지 않아도 

TCP가 ACK를 수신하지 못해서 패킷이 유실되었다는 것을 알아차릴 때까지의 TCP의 전송방식은 기본적으로 매우 복잡하다.

중복된 패킷은 수신자 측에서 폐기되며 순서가 없는 패킷은 재정렬되기 때문에 모든것이 신뢰할수 있고 정렬된다.


문제는 만약 패킷이 누락될 때마다 우리가 TCP를 통한 동기화를 하려고 할 때, 

패킷을 다시 보내기 위해서 동기화를 멈추거나 지연시킨다는 것이다.

그렇다, 심지어 최신 데이터를 받았을 때도 최신 데이터를 큐에 넣고,

그리고 당신은 누락된 패킷이 재전송될때까지 이것에 접근할 수 없다.

패킷을 다시 보내려면 얼마나 걸릴까?

이것은 TCP로 데이터를 다시 보내 해결하기 위해서 최소 왕복하는 대기시간이 필요하다.

그러나 평균적으로 이것은 두배의 왕복시간[RTT (Round Trip Time )], 

그리고 발신자가 수신자에게 재전송할 패킷이 도달하는데 걸리는 시간이 필요하다.

따라서 만약 당신이 125ms의 ping을 갖고 있다면, 당신은 최선의 경우에도 패킷을 재전송하기위해서 1/5초를 기다려야 하며, 최악의 경우에는 상황에 따라서 당신은 1/2초 또는 더 오랜 시간을 기다려야 한다.

(재전송하는것이 또 실패할 수 있다는 것을 생각해보아라)


만약 TCP가 네트워크 손실을 나타내는 패킷을  잃어버리고 이것이 작동한다면 무슨일이 벌어질까? 매우 재밌어 질것이다.



왜 당신은 TCP를 네트워크 시간에 민감한데이터에 사용하면 안될까?


실시간 FPS게임에 TCP를 사용하는 문제는 Web브라우저 또는 e메일, 대부분의 App과는 비슷하지 않다는 것이다. 멀티플레이어 게임은 실시간으로 패킷의 전달을 요청한다.

당신의 게임 중 많은 부분, 플레이어 입력과 케릭터의 위치를 예로 들 수 있다.

이것은 실제로 몆초전에 어떤일이 일어났는지 신경쓰지 않으며, 당신은 오직 최신 데이터만 신경쓰면 된다. TCP는 이점을 염두해두고 설계되지 않았다.


멀티플레이어 게임의 매우 단순한 예를 고려해보면, 일종의 '슈터'같은 액션게임이 있다.

당신은 아주 간단한 방법의 네트워크를 원한다.

당신이 매 프레임마다 크라이언트에서 서버로 보낸 입력, 그리고 서버에서 매 프레임마다 처리하는 각각의 플레이어로부터의 입력, 시뮬레이션 처리, 게다가 랜더링을 위해서 클라이언트에게 게임 오브젝트의 현재 위치를 보낸다.


그래서 우리의 단순한 멀티플레이 게임에서는, 패킷을 잃을 때마다,

패킷을 다시 보내는 동안 모두 멈추고 기다려야한다.

클라이언트 게임 오브젝트에서 업데이트 받는것을 멈추면 그것들은 여전히 서있는것처럼 보일 것이다. 그리고 서버에서 클라이언트로부터 얻는 입력이 멈춘다.

그러면 유저는 움직이거나 솔 수 없다.

다시 보낸 패킷이 마침내 도착했을 때, 당신은 낡은것을 받고, 

이미 당신이 신경쓰지 않는 지나간 정보를 받는다.

덧붙여서 같은 시간에 도착한 패킷들은 다시 보내는 동안 큐에 저장된 채로 기다리고,

당신은 같은 프레임 내에서 모든 패킷에 대한 처리를 해야 한다.

모두다 엉망이다!


불행히도, 이 것을 고치기 위해서 TCP를 사용해서 당신이 할수 있는 것은 없고, 당신이 원하지 않더라도 이것은 TCP의 기본적인 성질이다.

이것은 그저 신뢰할 수 없는, 패킷 기반의 인터넷을 신뢰성있고 정렬된 스트림으로 보이게 할 뿐입니다.



신뢰성있고 정렬된 스트림은 우리가 원하지 않는 것입니다.

우리는 데이터 손실때문에 재발신을 기다리는 일 없이 클라이언트에서 서버로 가능한 빠르게 받은 데이터를 원합니다.


이것이 우리가 왜 실시간 데이터 네트워킹을 위해서 TCP를 절대 사용하면 안되는지에 대한 이유입니다.


잠깐, TCP와 UDP를 동시에 사용하면 안되는 이유는?


플레이어 입력, 상태와 같은 실시간 게임 데이터를 통해서, 오직 가장 최근의 데이터와 관련되어 있다. 그러나 다른 유형의 데이터는, 하나의 장비에서 다른 장비로 보낸 일련의 명령어라고 말하면, 신뢰성과 순서가 매우 중요할 수 있습니다.


UDP를 플레이어 입력과 상태에, TCP는 신뢰할 수 있고 정렬된 데이터에 사용하는것이 매력적입니다.

만약 당신이 예리하다면 아마도 신뢰할수 있고 정렬된 명령의 "Stream", 아마도 레벨로딩에 대한 것, 그리고 AI에 대한 다른것, 이 여러개가 있다는 점을 스스로 추측할 지도 모릅니다.

"글쎄, 난 난 AI 커맨드가 레벨로딩 커맨드를 보관한 패킷이 손실된다고 해도 사라지지 않기를 원해, 이건 상관없거든"

당신이 맞다, 그러니 커맨드의 흐름을 TCP소켓를 통해 구현하려고 시도할지도 모른다.


표면적으로는, 이것은 매우 좋은 생각같다. 문제는 이것이 TCP와 UDP는 모두 IP의 위에 만들어졌기 때문에, 각각의 프로토콜에 의해 보내진 내부패킷은 서로에게 영향을 줄수 있다는 것이다.

정확히 그것들이 어떻게 서로 영향을 미치는지는 꽤 복잡하고 어떻게 TCP가 신뢰성과 흐름을 제어하는지와 관련되어 있다, 그러나 근본적으로는 당신은 TCP가 UDP패킷들에서 패킷손실을 유발하는 경향이 있다는 것을 기억해야한다.

좀더 자세한정보는 "링크"에 있다.


또한, UDP와 TCP를 섞는것은 꽤 복잡하다.

만약 당신이 UDP와 TCP를 섞는다면 당신은 일정한 양의 제어권을 잃는다

[구현에서 컨트롤할수 있는 부분이 적어진다는 의미인듯.]

아마 당신은 TCP를 사용하는 것보다 더 효과적인 방법을 구현할 수 있을 것이다.

근데 그게 당신이 필요하는것 보다 더 적합한가??

만약 당신이 신뢰성과 정렬된 데이터를 원한다면. 이것은 가능하다, 

제공된 데이터가 사용가능한 대역폭에 비해 상대적으로 작으면 TCP를 통해 빠르고 더 안정적으로 보낼 수 있습니다.

거기에, 만약 당신이 집 인터넷으로 다른 누군가에게 말을 하기 위해서 연결을 가능하게 하기 위해서 NAT을 할 필요가 있다면, 이 NAT은 일종의 고통스러운 한번의 UDP 그리고 한번의 TCP(이게 가능할지는 모르겠지만)를 해야만 한다.



결론 


내가 추천하는 것은 당신이 UDP만 사용하라는 것도 아니고, 

그러나 당신이 오직 UDP를 게임 프로토콜로 사용하라는 것도 아니다.

TCP와 UDP를 섞지 말라는 것이다. 

대신 당신이 직접만든 UDP 프로토콜 안에 당신이 사용하길 원하는 TCP의 특별한 조각을 구현하는 방법을 배워라.

[UDP기반으로 신뢰성이 필요하다면 신뢰성 구현하는 걸 배우라는 의미인듯]


물론 이것은 HTTP에서 RESTfull 서비스를 사용해 게임을 하는 동안 다른사람과 말을 하는것은 문제가 안된다.

그것은 내가 말하려했던 것이 아니다.

당신의 게임이 돌아가는 동안의 TCP연결은 모든것을 가져오지는 않는다.

요점은, 당신의 게임 프로토콜을 UDP와 TCP로 구분하지 말라는 것이다.

게임이 돌아가는 동안 UDP를 통해 당신의 게임 프로토콜을 유지한다면 당신은

당신이 보냈고 받은 데이터와 신뢰성, 정렬 및 혼잡함을 방지하는 것을 완벽하게 구현할 수 있습니다.


이 시리즈의 나머지 기사는 당신이 어떻게 이를 구현하고, 가상 연결을 기반으로 UDP위에 프로토콜을 만듬으로부터, 신뢰성을 구축하고, 흐름을 통제와 혼잡성 방지를 보여줍니다.


다음 기사 : 패킷 전송과 수신






반응형
Posted by Sweetmeats_boy
이전버튼 1 이전버튼

블로그 이미지
Sweetmeats_boy

태그목록

Yesterday
Today
Total

달력

 « |  » 2024.11
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함