# \[1.6 버전] 서버 간 LAN 통신기

{% hint style="danger" %}
LanServer, LanClient는 1.7 버전부터 퇴역 되었습니다. \
LanServer, LanClient의 역할을 <mark style="color:orange;">NetServer</mark>, <mark style="color:orange;">NetClient</mark>가 대신 합니다. <br>

**참고**\
[**ProudNet 1.6 Lan Module 에서 1.7 Net Module 로 마이그레이션**](#proudnet-1.6-lan-module-1.7-net-module)
{% endhint %}

## LAN 통신기의 특징

ProudNet 서버와 네트워크와 서버 간 LAN 통신기의 차이점은 다음과 같습니다.

<table data-full-width="false"><thead><tr><th width="231">구분</th><th width="244">ProudNet 서버와 네트워크</th><th>서버 간 LAN 통신기</th></tr></thead><tbody><tr><td>주요 용도</td><td>일반 사용자 어플리케이션과 서버와의 통신</td><td>분산 서버 구조에서 각 서버 간의 통신</td></tr><tr><td>NAT 장치 투과</td><td>YES</td><td>NO</td></tr><tr><td>P2P relay(relay)</td><td>YES</td><td>NO</td></tr><tr><td>클라이언트-서버간 통신 프로토콜</td><td>TCP and UDP</td><td>TCP</td></tr><tr><td>P2P 통신 프로토콜</td><td>(Reliable) UDP</td><td>TCP</td></tr><tr><td>클라이언트의 콜백 방식</td><td>Poll (<mark style="color:orange;">Proud.CNetClient.FrameMove</mark>에서 콜백)</td><td>스레드풀에서 콜백</td></tr></tbody></table>

<mark style="color:orange;">lan\_main</mark>는 다음과 같이 호스트 간 고속 통신을 제공합니다.

> * TCP 만 사용하기 때문에 서버 하드웨어의 통신 가속화(TCP Offload Engine)를 사용합니다.
> * <mark style="color:orange;">Client</mark> 와 달리 이벤트 및 수신 메시지를 스레드 풀에서 콜백합니다. \
>   물론, 서버 측 또한 thread pool에서 콜백이 발생합니다.

## LAN 통신기 사용법

ProudNet 서버와 네트워크과 LAN 통신기의 사용법은 거의 동일합니다.&#x20;

다음은 API 차이점입니다.

<table><thead><tr><th width="221">구분</th><th width="261">ProudNet 서버와 네트워크</th><th>서버 간 LAN 통신기</th></tr></thead><tbody><tr><td>Server</td><td>Proud.CNetServer</td><td>Proud.CLanServer</td></tr><tr><td>Client</td><td>Proud.CNetClient</td><td>Proud.CLanClient</td></tr><tr><td>Server event handler</td><td>Proud.INetServerEvent</td><td>Proud.ILanServerEvent</td></tr><tr><td>Client event handler</td><td>Proud.INetClientEvent</td><td>Proud.ILanClientEvent</td></tr><tr><td>Message pool method</td><td>Proud.CNetClient.FrameMove</td><td>None (callback in thread pool)</td></tr></tbody></table>

## LAN 통신기의 P2P 통신

<mark style="color:orange;">Proud.CLanClient</mark> 호스트 간의 P2P 통신에서는 TCP 프로토콜이 사용됩니다.&#x20;

<mark style="color:orange;">Proud.CLanServer.CreateP2PGroup</mark> 등에 의해 호스트 간 P2P 통신이 성사되는 순간 P2P 메시징을 시작하는 경우 피어 간 TCP 연결이 완료되기 전까지는 보내려는 메시지가 각 호스트의 로컬 queue에 저장됩니다. 저장된 메시지는 TCP 연결이 성사 되자마자 즉시 전송을 시작합니다.

TCP 연결이 성사되자마자 <mark style="color:orange;">Proud.ILanClientEvent.OnP2PConnectionEstablished</mark>, <mark style="color:orange;">Proud.ILanServerEvent.OnP2PConnectionEstablished</mark> 가 콜백됩니다.&#x20;

반대로 TCP 연결이 해제되면 <mark style="color:orange;">Proud.ILanClientEvent.OnP2PDisconnected</mark>, <mark style="color:orange;">Proud.ILanServerEvent.OnP2PDisconnected</mark>가 콜백됩니다.&#x20;

<mark style="color:orange;">Proud.ILanClientEvent.OnGroupP2PConnectionComplete</mark>, <mark style="color:orange;">Proud.ILanServerEvent.OnGroupP2PConnectionComplete</mark> 는 P2P 그룹 내의 모든 멤버들이 TCP 연결이 성사되면 콜백됩니다.

## LAN 통신기에서의 thread pool

<mark style="color:orange;">Proud.CLanClient</mark> 는 event 콜백과 RMI 콜백은 스레드 풀의 스레드에서 발생합니다. 그리고 이 스레드 풀은 <mark style="color:orange;">Proud.CLanClient</mark> 에서 준비하기 때문에 <mark style="color:orange;">Proud.CNetClient.FrameMove</mark>에 대응하는 함수는 없습니다.

<mark style="color:orange;">Proud.CLanConnectionParam.m\_netWorkerThreadCount</mark> 에서는 클라이언트에서 가지고 있을 스레드 풀의 스레드 갯수를 지정할 수 있습니다.

<br>

## LAN 클라이언트의 연결 해제 처리

LAN 클라이언트는 연결 과정( <mark style="color:orange;">CLanClient.Connect</mark> ) 에서 <mark style="color:orange;">user worker thread pool</mark> 을 만들며, 연결 해제 과정 ( <mark style="color:orange;">CLanClient.Disconnect</mark> ) 에서 그 pool 을 제거하기 때문에 LAN 클라이언트는 연결 해제 또는 연결 명령을 <mark style="color:orange;">user worker thread</mark>에서 시행할 수 없습니다.&#x20;

만약 시행 하면 <mark style="color:orange;">Proud.Exception</mark>이 발생합니다.

<br>

## LAN 통신기의 RMI

[**RMI**](/proudnet/proudnet/using_pn/rmi.md) 사용법과 동일합니다.

## 서버 간 통신에서 시간 동기화하기

[**클라이언트에서 서버 시간 얻기**](/proudnet/proudnet/using_pn/server_client/using_client.md#undefined-3) 사용법과 동일합니다.

## ProudNet 1.6 Lan Module 에서 1.7 Net Module 로 마이그레이션

### - 1.6 Lan Module에서 1.7 Net Module로 변경 시 주의사항

<mark style="color:orange;">NetClient.Connect()</mark> 호출 시 thread model 지정이 필요 합니다.

호출 시 <mark style="color:orange;">m\_userWorkerThreadModel</mark> 에 파라미터를 넣어 user 콜백이 여러 스레드에서 받아질 수 있게 해야합니다.&#x20;

또는 <mark style="color:orange;">m\_externalUserWorkerThreadPool</mark> 파라미터에 만들어 놓은 스레드 풀 객체를 붙입니다.

이 스레드 풀은 여러 스레드를 가집니다.

{% tabs %}
{% tab title="C++" %}

```cpp
void CFarmClient::Connect()
{
    CNetConnectionParam p1;
    p1.m_protocolVersion = CFarmSettings::GetSharedPtr()->GetFarmVersion();
    p1.m_serverIP = L"localhost";
    p1.m_serverPort = CFarmSettings::GetSharedPtr()->GetFarmServerPort();
    p1.m_timerCallbackIntervalMs = 1000;
 
    // m_lanClient의 이벤트 처리를 user worker thread pool에서 처리하기 위해. 
    // 그리고 FrameMove를 호출 할 필요가 없게 하기 위해.
    p1.m_userWorkerThreadModel = ThreadModel_MultiThreaded;
 
    // outerror는 에러가 발생할 경우에만 힙에 할당된 ErrorInfo를 가리키게 됩니다.
    // Connect 호출후에 outerror를 사용하시려면 NULL인지 체크후 사용하셔야 됩니다.
    ErrorInfoPtr outerror;
    m_lanClient->Connect(p1, outerror);
}
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
서버 간에 통신할 때 기존 TCP 통신에서 UDP base 통신으로 변경되었으며, UDP Port 관련 방화벽 작업이 필요합니다.
{% endhint %}

### - 1.6 Lan Module 에서 1.7 Net Module로 변경 방법

> 1. **1.7 라이브러리를 준비합니다.**\
>    라이브러리는 <mark style="color:orange;"><설치 폴더>/ProudNet/lib/</mark> 에 있습니다.
> 2. **함수 명을 Lan 에서 Net 으로 변경 합니다.**\
>    변경 대상은 클래스, 함수, 메소드 모두 포함. 대부분 1:1 matching 이라 큰 변화 없이 전환이 가능합니다.

### - 1.6 Sample/SimpleLan 예제를 1.7로 마이그레이션 하는 예제

> * **LanCommon** → <mark style="color:orange;">NetCommon</mark>
> * **UUID** → <mark style="color:orange;">PNGUID</mark>
> * **Guid::From(guid)** → <mark style="color:orange;">Guid(guid)</mark>

<figure><img src="/files/0FDtkrjjjzSyV2tVsDmr" alt=""><figcaption><p>LanToNet_Common_01</p></figcaption></figure>

> * **LanServer** → <mark style="color:orange;">NetServer</mark>
> * **CLanServerEventSink** → <mark style="color:orange;">CNetServerEventSink</mark>
> * **OVERRIDE** → <mark style="color:orange;">PN\_OVERRID</mark>
> * **CLanServer** → <mark style="color:orange;">CNetServer</mark>
> * **CStartLanServerParameter** → <mark style="color:orange;">StartServerParameter</mark>
> * **p1.m\_tcpPort = g\_ServerPort** → <mark style="color:orange;">p1.m\_tcpPort .Add(g\_ServerPort)</mark>

<figure><img src="/files/WyX8y951T2KmYhRyW0FR" alt=""><figcaption></figcaption></figure>

> * **LanClient** → <mark style="color:orange;">NetClient</mark>
> * **CLanClient** → <mark style="color:orange;">CNetClient</mark>
> * **ILanClientEvent** → <mark style="color:orange;">INetClientEvent</mark>
> * **OVERRIDE** → <mark style="color:orange;">PN\_OVERRID</mark>
> * **CLanClient::Create()** → <mark style="color:orange;">CNetClient::Create()</mark>
> * **CLanConnectionParam** → <mark style="color:orange;">CNetConnectionParam</mark>
> * **ProudNetServer.h** → <mark style="color:orange;">ProudNetClient.h</mark>

<figure><img src="/files/nMWT6Skpfm4xcJkhLRJ2" alt=""><figcaption></figcaption></figure>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.proudnet.com/proudnet/pn_reference_ko/notes/communcation_lan.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
