iconDreamine
← 목록

Dreamine.Communication.Sockets

stablev1.0.2

TCP/UDP 소켓 통신 구현 — 고성능 비동기 소켓 클라이언트/서버.

#communication#dreamine#messaging#sockets#tcp#transport
TFM net8.0Package Dreamine.Communication.Sockets참조 Dreamine.Communication.Abstractions, Dreamine.Communication.Core

Dreamine.Communication.Sockets

Dreamine.Communication.Sockets는 Dreamine Communication 계열 패키지의 일부입니다.

이 패키지는 TCP 및 UDP 소켓 기반 전송 구현체를 제공하며, 소켓 연결 관련 책임을 애플리케이션 계층 및 다른 전송 패키지와 분리합니다.

➡️ English Version

설명

Dreamine Communication을 위한 TCP/UDP 소켓 전송 패키지입니다. TcpClientTransport, TcpServerTransport, UdpTransport 구현체를 제공하며, 선택된 프로토콜 어댑터와 (TCP의 경우) 프레임 코덱을 통해 MessageEnvelope를 송수신합니다.

패키지 역할

Dreamine.Communication.Abstractions
    ↑
Dreamine.Communication.Core
    ↑
Dreamine.Communication.Sockets

Sockets는 구체적인 TCP 통신 경계만 담당합니다.

  • TCP Client 연결 열기 및 닫기.
  • TCP Server Listener 시작 및 중지.
  • TCP Client Accept 처리.
  • NetworkStream 기반 수신 루프 실행.
  • 연결된 Client 대상 Server 메시지 Broadcast 송신.
  • IMessageProtocolAdapter를 통한 송신 MessageEnvelope 인코딩.
  • IMessageFrameCodec을 통한 스트림 데이터 프레임 처리.

이 패키지는 UI 상태, 애플리케이션 명령 규칙, 비즈니스 라우팅 정책, Serial Port 로직, RabbitMQ 연결 로직, WPF 전용 로직을 소유하면 안 됩니다.

주요 기능

  • TCP Client Transport
  • TCP Server Transport
  • UDP Datagram Peer-to-Peer Transport
  • MessageEnvelope 기반 송수신 흐름
  • 프로토콜 어댑터 설정 가능
  • 프레임 코덱 설정 가능 (TCP 전용. UDP는 Datagram 기반이므로 사용하지 않음)
  • Core의 공통 JSON 직렬화 및 프로토콜 어댑터 사용
  • Core의 공통 스트림 프레임 처리 사용
  • 연결 상태 관리를 포함한 비동기 수신 루프
  • Server에서 연결된 Client 전체 대상 Broadcast 송신

주요 구성 요소

타입 역할
TcpClientTransport TCP Client 연결을 위한 IMessageTransport 구현체입니다.
TcpServerTransport TCP Server Listener 및 연결된 Client 처리를 위한 IMessageTransport 구현체입니다.
UdpTransport UDP Datagram Peer-to-Peer 통신을 위한 IMessageTransport 구현체입니다.
TcpClientTransportOptions TCP Client 연결 설정 모델입니다.
TcpServerTransportOptions TCP Server Listener 설정 모델입니다.
UdpTransportOptions UDP Local/Remote 엔드포인트 설정 모델입니다.
SocketCommunicationException 소켓 통신 전용 예외 타입입니다.

TcpClientTransport

TcpClientTransport는 공통 IMessageTransport 계약을 구현합니다.

기본 생성자 동작:

Protocol adapter : DreamineEnvelopeProtocolAdapter
Frame codec      : LengthPrefixedMessageFrameCodec

이 기본값은 Dreamine 간 TCP 통신에 적합합니다. 외부 툴, TCP 터미널, PLC Gateway 소프트웨어, 검사 장비, Raw 문자열 테스트에는 프로토콜 어댑터와 프레임 코덱을 명시적으로 전달해야 합니다.

Raw Text Client 예시:

using System.Text;
using Dreamine.Communication.Core.Framing;
using Dreamine.Communication.Core.Protocols;
using Dreamine.Communication.Sockets.Clients;
using Dreamine.Communication.Sockets.Options;

var client = new TcpClientTransport(
    new TcpClientTransportOptions
    {
        Host = "127.0.0.1",
        Port = 15002
    },
    new PlainTextProtocolAdapter(
        Encoding.UTF8,
        "tcp.raw.available",
        "Tcp.RawAvailable"),
    new RawAvailableMessageFrameCodec());

client.MessageReceived += (_, message) =>
{
    var text = Encoding.UTF8.GetString(message.Payload);
    Console.WriteLine($"RX: {text}");
};

await client.ConnectAsync();

TcpServerTransport

TcpServerTransport는 공통 IMessageTransport 계약을 구현합니다.

기본 생성자 동작:

Protocol adapter : DreamineEnvelopeProtocolAdapter
Frame codec      : LengthPrefixedMessageFrameCodec

Server는 TcpListener를 시작하고, 여러 TCP Client를 Accept하며, Client별 수신 루프를 생성합니다. 송신 메시지는 현재 연결된 모든 Client에게 Broadcast됩니다.

Raw Text Server 예시:

using System.Text;
using Dreamine.Communication.Core.Framing;
using Dreamine.Communication.Core.Protocols;
using Dreamine.Communication.Sockets.Options;
using Dreamine.Communication.Sockets.Servers;

var server = new TcpServerTransport(
    new TcpServerTransportOptions
    {
        Host = "0.0.0.0",
        Port = 15002
    },
    new PlainTextProtocolAdapter(
        Encoding.UTF8,
        "tcp.raw.available",
        "Tcp.RawAvailable"),
    new RawAvailableMessageFrameCodec());

server.MessageReceived += (_, message) =>
{
    var text = Encoding.UTF8.GetString(message.Payload);
    Console.WriteLine($"RX: {text}");
};

await server.ConnectAsync();

TcpClientTransportOptions

옵션 기본값 의미
Host 127.0.0.1 연결할 TCP Server Host입니다.
Port 0 연결할 TCP Server Port입니다. 연결 전 1~65535 범위여야 합니다.
ReceiveBufferSize 8192 TCP 수신 버퍼 크기입니다.
SendBufferSize 8192 TCP 송신 버퍼 크기입니다.
ConnectTimeoutMs 5000 TCP 연결 타임아웃(ms)입니다.

TcpServerTransportOptions

옵션 기본값 의미
Host 0.0.0.0 바인딩할 IP 주소입니다. 0.0.0.0은 모든 네트워크 인터페이스를 의미합니다.
Port 5000 TCP 수신 대기 Port입니다. 1~65535 범위여야 합니다.
Backlog 100 TCP Listener backlog 값입니다.
ReceiveBufferSize 8192 Accept된 Client에 적용할 수신 버퍼 크기입니다.
SendBufferSize 8192 Accept된 Client에 적용할 송신 버퍼 크기입니다.

Server Host 파싱은 현재 다음 값을 지원합니다.

  • 0.0.0.0
  • 127.0.0.1
  • localhost
  • 직접 입력한 IP 주소 문자열

외부 공개 서비스는 0.0.0.0 또는 특정 로컬 인터페이스 IP에 바인딩합니다. 로컬 테스트는 127.0.0.1을 사용합니다.

Protocol Adapter와 Frame Codec

TCP는 스트림 기반입니다. 애플리케이션 메시지 경계를 보존하지 않습니다. 그래서 메시지 의미와 메시지 경계 처리를 의도적으로 분리합니다.

책임 타입
Byte와 MessageEnvelope 상호 변환 IMessageProtocolAdapter
스트림에서 메시지 경계 판단 IMessageFrameCodec
TCP Socket 열기, 닫기, 송신, 수신 TcpClientTransport / TcpServerTransport

권장 조합

시나리오 Protocol Adapter Frame Codec
Dreamine 간 TCP 통신 DreamineEnvelopeProtocolAdapter LengthPrefixedMessageFrameCodec
각 메시지가 CRLF 또는 LF로 끝나는 Text Protocol PlainTextProtocolAdapter DelimiterMessageFrameCodec
단순 TCP 테스트 툴이 구분자 없이 Raw Text 전송 PlainTextProtocolAdapter RawAvailableMessageFrameCodec
줄 끝이 있는 JSON Text Protocol RawJsonProtocolAdapter DelimiterMessageFrameCodec
Custom Binary TCP Protocol Custom Protocol Adapter Custom Frame Codec

RawAvailableMessageFrameCodec 지원

RawAvailableMessageFrameCodec은 이 패키지가 아니라 Dreamine.Communication.Core에 정의됩니다. 그래도 TcpClientTransportTcpServerTransport는 모든 IMessageFrameCodec을 받을 수 있으므로 그대로 사용할 수 있습니다.

이 모드는 TCP 툴 또는 외부 장비가 다음처럼 단순 값을 보낼 때 유용합니다.

test1

위 값에 다음 항목이 없어도 수신 처리가 가능합니다.

  • Dreamine Envelope
  • Length Prefix
  • CRLF
  • LF

설정 예시:

var transport = new TcpServerTransport(
    options,
    new PlainTextProtocolAdapter(
        Encoding.UTF8,
        "tcp.raw.available",
        "Tcp.RawAvailable"),
    new RawAvailableMessageFrameCodec());

이 조합을 사용하면 Hercules 같은 수동 TCP 테스트 툴에서 단순 문자열을 보내도 MessageReceived가 발생합니다.

중요한 TCP Stream 주의사항

TCP는 Byte Stream입니다. RawAvailableMessageFrameCodec은 한 번의 Stream Read에서 반환된 Byte를 하나의 메시지로 처리합니다.

수동 테스트에는 편하지만, 엄격한 메시지 경계 규칙은 아닙니다. 타이밍과 버퍼 상태에 따라 여러 번의 송신이 합쳐지거나, 한 번의 송신이 쪼개질 수 있습니다.

가능한 수신 결과 예시:

test1test2

또는:

te
st1

운영용 TCP Protocol에는 아래 방식 중 하나를 권장합니다.

  • Dreamine 내부 통신에는 LengthPrefixedMessageFrameCodec 사용.
  • CRLF, LF 또는 명확한 Delimiter 기반 DelimiterMessageFrameCodec 사용.
  • 고정 길이 Binary Frame 사용.
  • Protocol 전용 Custom IMessageFrameCodec 사용.

RawAvailableMessageFrameCodec은 호환성, 디버깅, 수동 테스트, 명확한 프레이밍 규칙이 없는 툴 대응용으로 사용하는 것이 맞습니다.

연결 상태

두 Socket Transport는 공통 ConnectionState enum을 통해 상태를 제공합니다.

상태 TcpClientTransport TcpServerTransport
Disconnected Client 연결이 끊긴 상태입니다. Listener가 중지된 상태입니다.
Connecting Client 연결 중입니다. Server Listener 시작 중입니다.
Connected Client가 연결되었고 수신 루프가 동작 중입니다. Listener와 Accept Loop가 동작 중입니다.
Disconnecting Client 연결 종료 중입니다. Server 중지 및 Client 정리 중입니다.
Faulted 연결 또는 수신 루프 오류가 발생했습니다. Listener, Accept Loop 또는 Socket 작업 오류가 발생했습니다.

송신 동작

TcpClientTransport.SendAsync는 연결된 Server로 인코딩된 Frame 하나를 전송합니다.

TcpServerTransport.SendAsync는 현재 연결된 모든 Client에게 인코딩된 Frame 하나를 Broadcast합니다. 송신 중 Client 연결이 끊겼거나 오류가 발생하면 해당 Client는 Server 연결 목록에서 제거됩니다.

오류 처리

Transport는 Socket을 열기 전에 Options를 검증합니다. 잘못된 설정은 조기에 실패합니다.

예시:

  • 비어 있는 Host
  • Port <= 0
  • Port > 65535
  • 0 이하의 버퍼 크기
  • 0 이하의 Client 연결 타임아웃
  • 0 이하의 Server backlog

런타임 Socket 오류는 Transport 상태를 Faulted로 변경할 수 있습니다. 애플리케이션 레벨 복구는 Transport를 Dispose 또는 Disconnect한 뒤, Socket 조건을 수정하고 다시 연결하거나 Server를 재시작하는 방식으로 처리합니다.

사용 예시: Dreamine 간 TCP 통신

using Dreamine.Communication.Abstractions.Models;
using Dreamine.Communication.Sockets.Clients;
using Dreamine.Communication.Sockets.Options;
using Dreamine.Communication.Sockets.Servers;

var server = new TcpServerTransport(
    new TcpServerTransportOptions
    {
        Host = "127.0.0.1",
        Port = 15001
    });

server.MessageReceived += (_, message) =>
{
    Console.WriteLine($"Server RX: {message.Name}");
};

await server.ConnectAsync();

var client = new TcpClientTransport(
    new TcpClientTransportOptions
    {
        Host = "127.0.0.1",
        Port = 15001
    });

await client.ConnectAsync();

await client.SendAsync(new MessageEnvelope
{
    Name = "Sample.Ping",
    Route = "sample.tcp.ping",
    Payload = []
});

사용 예시: CRLF Text TCP

using System.Text;
using Dreamine.Communication.Core.Framing;
using Dreamine.Communication.Core.Protocols;
using Dreamine.Communication.Sockets.Clients;
using Dreamine.Communication.Sockets.Options;

var client = new TcpClientTransport(
    new TcpClientTransportOptions
    {
        Host = "127.0.0.1",
        Port = 15002
    },
    new PlainTextProtocolAdapter(
        Encoding.UTF8,
        "tcp.plaintext",
        "Tcp.PlainText"),
    new DelimiterMessageFrameCodec(
        "\r\n",
        Encoding.UTF8,
        1024 * 1024));

await client.ConnectAsync();

설계 원칙

  • 구체 Socket 구현체를 상위 레이어와 분리합니다.
  • Dreamine.Communication.Abstractions 계약에 의존합니다.
  • Core의 프로토콜 어댑터와 프레임 코덱을 재사용합니다.
  • Socket 연결 제어와 Payload 해석을 분리합니다.
  • 패키지 책임을 작고 명확하게 유지합니다.
  • 단방향 의존성 흐름을 유지합니다.
  • 향후 TCP Protocol 및 Custom Codec을 추가해도 애플리케이션 로직을 변경하지 않도록 합니다.

의존성

  • Dreamine.Communication.Abstractions
  • Dreamine.Communication.Core

대상 프레임워크

net8.0

관련 패키지

  • Dreamine.Communication.Abstractions
  • Dreamine.Communication.Core
  • Dreamine.Communication.Sockets
  • Dreamine.Communication.Serial
  • Dreamine.Communication.RabbitMQ
  • Dreamine.Communication.FullKit
  • Dreamine.Communication.Wpf

UDP Transport

Dreamine.Communication.Sockets는 UDP Peer 방식 Transport도 제공합니다. UDP는 Datagram 기반이므로 LengthPrefixedMessageFrameCodec, DelimiterMessageFrameCodec, RawAvailableMessageFrameCodec 같은 Stream Frame Codec을 사용하지 않습니다.

권장 UDP 구조는 다음과 같습니다.

UDP Datagram -> IMessageProtocolAdapter -> MessageEnvelope
MessageEnvelope -> IMessageProtocolAdapter -> UDP Datagram

샘플은 로컬 Loopback 테스트를 위해 두 개의 UDP Peer를 사용합니다.

Peer A: 127.0.0.1:16001 -> 127.0.0.1:16002
Peer B: 127.0.0.1:16002 -> 127.0.0.1:16001

Dreamine 내부 Peer 간 테스트는 Start Loopback을 사용합니다. Hercules 같은 외부 UDP 툴과 테스트할 때는 로컬 포트 충돌을 피하기 위해 Peer 하나만 연결합니다.

Hercules 테스트 예시는 다음과 같습니다.

Dreamine Peer A Local : 16001
Dreamine Peer A Remote: 16002
Hercules Local port   : 16002
Hercules Target port  : 16001

이 경우 Dreamine 샘플에서는 Connect ASend Peer A를 누릅니다.

UDP 사용 예시

using System.Text;
using Dreamine.Communication.Abstractions.Models;
using Dreamine.Communication.Core.Protocols;
using Dreamine.Communication.Sockets.Options;
using Dreamine.Communication.Sockets.Udp;

var peerA = new UdpTransport(
    new UdpTransportOptions
    {
        LocalHost = "127.0.0.1",
        LocalPort = 16001,
        RemoteHost = "127.0.0.1",
        RemotePort = 16002,
        ReuseAddress = true
    },
    new PlainTextProtocolAdapter(
        Encoding.UTF8,
        "udp.plaintext",
        "Udp.PlainText"));

peerA.MessageReceived += (_, message) =>
{
    var text = Encoding.UTF8.GetString(message.Payload);
    Console.WriteLine($"Peer A RX: {text}");
};

await peerA.ConnectAsync();

await peerA.SendAsync(new MessageEnvelope
{
    Name = "Udp.PeerA.Send",
    Route = "udp.plaintext",
    Payload = Encoding.UTF8.GetBytes("hello"),
    Headers = new Dictionary<string, string>
    {
        ["ContentType"] = "text/plain",
        ["Protocol"] = "PlainText"
    }
});

Loopback 로컬 테스트는 LocalPort와 RemotePort를 서로 맞바꾼 두 번째 UdpTransport(Peer B)를 함께 생성하여 사용합니다.

외부 Text Encoding

TCP와 UDP는 UTF-8을 사용하지 않는 외부 툴 또는 장비와 통신할 수 있습니다. 따라서 샘플에서는 외부 Text 계열 모드에 대해 Encoding 선택 기능을 제공합니다.

Encoding 권장 용도
UTF-8 현대 시스템 및 Dreamine ↔ Dreamine 통신 기본값
CP949 레거시 한글 Windows 툴, Hercules 한글 테스트, 오래된 장비 프로토콜

Encoding 선택은 Protocol Adapter 경계에서 적용됩니다. TcpClientTransport, TcpServerTransport, UdpTransport의 책임이 아닙니다.

라이선스

이 프로젝트는 MIT 라이선스를 따릅니다.

구조 다이어그램

classDiagram
    class TcpClient {
        -string _host
        -int _port
        +IsConnected bool
        +ConnectAsync() Task
        +DisconnectAsync() Task
        +SendAsync(byte[]) Task
        +ReceiveAsync() Task~byte[]~
        +DataReceived event
    }
    class UdpClient {
        -string _host
        -int _port
        +SendAsync(byte[], IPEndPoint) Task
        +ReceiveAsync() Task~UdpReceiveResult~
        +StartListening() void
        +StopListening() void
    }
    class TcpServer {
        -int _port
        +Start() Task
        +Stop() Task
        +ClientConnected event
        +DataReceived event
        +Broadcast(byte[]) Task
    }
    class SocketPool {
        -int _maxConnections
        +Acquire() Task~TcpClient~
        +Release(TcpClient) void
    }
    class ConnectionClientBase {
        <<abstract>>
    }
    ConnectionClientBase <|-- TcpClient
    TcpServer o-- TcpClient
    SocketPool o-- TcpClient

API 문서

타입

SocketCommunicationException

\if KO TCP 또는 UDP 소켓 연결과 송수신 과정에서 발생한 통신 오류를 나타냅니다. \endif \if EN Represents a communication error raised during TCP or UDP socket connection and transfer. \endif

TcpClientConnectionEntry

\if KO 서버가 수락한 TCP 클라이언트의 식별자, 소켓, 연결 시각 및 송신 동기화를 보관합니다. \endif \if EN Stores the identifier, socket, connection time, and send synchronization for a TCP client accepted by the server. \endif

TcpClientTransport

\if KO TCP 클라이언트 연결에서 구성 가능한 프레임과 프로토콜로 메시지를 송수신합니다. \endif \if EN Sends and receives framed protocol messages over a TCP client connection. \endif

TcpClientTransportOptions

\if KO TCP 클라이언트의 서버 주소, 버퍼 및 연결 제한 시간을 구성합니다. \endif \if EN Configures the server address, buffers, and connection timeout for a TCP client. \endif

TcpServerSendTargetMode

\if KO TCP 서버 송신 시 메시지를 전달할 연결 클라이언트 선택 정책입니다. \endif \if EN Specifies how connected clients are selected for a TCP server send operation. \endif

TcpServerTransport

\if KO 여러 TCP 클라이언트의 연결, 수신 및 대상별 메시지 송신을 관리합니다. \endif \if EN Manages connections, receiving, and targeted message sending for multiple TCP clients. \endif

TcpServerTransportOptions

\if KO TCP 서버의 수신 주소, 대기열, 버퍼 및 기본 송신 대상을 구성합니다. \endif \if EN Configures the listen address, backlog, buffers, and default send targets for a TCP server. \endif

UdpTransport

\if KO UDP 데이터그램을 프로토콜 메시지로 변환해 송수신하는 전송 계층입니다. \endif \if EN Sends and receives protocol messages as UDP datagrams. \endif

UdpTransportOptions

\if KO UDP 소켓의 로컬·원격 엔드포인트, 버퍼 및 소켓 동작을 구성합니다. \endif \if EN Configures local and remote endpoints, buffers, and socket behavior for UDP transport. \endif

SocketCommunicationException

#ctor Method

\if KO 기본 메시지로 새 소켓 통신 예외를 초기화합니다. \endif \if EN Initializes a new socket communication exception with the default message. \endif

#ctor Method

\if KO 지정한 오류 메시지로 새 소켓 통신 예외를 초기화합니다. \endif \if EN Initializes a new socket communication exception with the specified message. \endif

message— \if KO 오류 원인을 설명하는 메시지입니다. \endif \if EN The message describing the error. \endif
#ctor Method

\if KO 지정한 오류 메시지와 내부 예외로 새 소켓 통신 예외를 초기화합니다. \endif \if EN Initializes a new socket communication exception with a message and inner exception. \endif

message— \if KO 오류 원인을 설명하는 메시지입니다. \endif \if EN The message describing the error. \endif
innerException— \if KO 현재 오류의 원인이 된 예외입니다. \endif \if EN The exception that caused the current error. \endif

TcpClientConnectionEntry

#ctor Method

\if KO 클라이언트 식별자, 소켓 및 연결 시각으로 연결 정보를 초기화합니다. \endif \if EN Initializes connection information with a client identifier, socket, and connection time. \endif

clientId— \if KO 연결 식별자입니다. \endif \if EN The connection identifier. \endif
client— \if KO 연결된 TCP 클라이언트입니다. \endif \if EN The connected TCP client. \endif
connectedAt— \if KO 연결이 수락된 시각입니다. \endif \if EN The time at which the connection was accepted. \endif
Client Property

\if KO 연결된 TCP 클라이언트를 가져옵니다. \endif \if EN Gets the connected TCP client. \endif

ClientId Property

\if KO 클라이언트 연결 식별자를 가져옵니다. \endif \if EN Gets the client connection identifier. \endif

ConnectedAt Property

\if KO 연결이 수락된 시각을 가져옵니다. \endif \if EN Gets the time at which the connection was accepted. \endif

SendLock Property

\if KO 이 클라이언트에 대한 프레임 쓰기를 직렬화하는 잠금을 가져옵니다. \endif \if EN Gets the lock that serializes frame writes to this client. \endif

TcpClientTransport

#ctor Method

\if KO 기본 Dreamine JSON 프로토콜과 길이 접두사 프레임으로 TCP 클라이언트를 초기화합니다. \endif \if EN Initializes the TCP client with the default Dreamine JSON protocol and length-prefixed framing. \endif

options— \if KO 서버 주소, 버퍼 및 연결 제한 시간 설정입니다. \endif \if EN The server address, buffer, and connection-timeout options. \endif
#ctor Method

\if KO TCP 설정과 사용자 지정 프로토콜 및 프레임 코덱으로 클라이언트를 초기화합니다. \endif \if EN Initializes the client with TCP options and custom protocol and frame codecs. \endif

options— \if KO 서버 주소, 버퍼 및 연결 제한 시간 설정입니다. \endif \if EN The server address, buffer, and connection-timeout options. \endif
protocolAdapter— \if KO 메시지와 외부 페이로드를 변환할 어댑터입니다. \endif \if EN The adapter that converts messages and external payloads. \endif
frameCodec— \if KO TCP 스트림의 메시지 경계를 처리할 코덱입니다. \endif \if EN The codec that handles message boundaries in the TCP stream. \endif
CleanupClient Method

\if KO 정리 예외를 전파하지 않고 TCP 클라이언트를 닫고 해제합니다. \endif \if EN Closes and disposes the TCP client without propagating cleanup exceptions. \endif

ConnectAsync Method

\if KO 제한 시간 내에 TCP 서버에 연결하고 백그라운드 수신 루프를 시작합니다. \endif \if EN Connects to the TCP server within the timeout and starts the background receive loop. \endif

cancellationToken— \if KO 연결 취소 요청을 감시하는 토큰입니다. \endif \if EN A token used to observe connection cancellation. \endif

반환: \if KO 비동기 TCP 연결 작업입니다. \endif \if EN A task representing the asynchronous TCP connection. \endif

DisconnectAsync Method

\if KO 수신 루프를 중지하고 TCP 클라이언트 연결을 닫습니다. \endif \if EN Stops the receive loop and closes the TCP client connection. \endif

cancellationToken— \if KO 정리 후 연결 해제 취소 여부를 확인하는 토큰입니다. \endif \if EN A token checked for cancellation after cleanup. \endif

반환: \if KO 비동기 연결 해제 작업입니다. \endif \if EN A task representing asynchronous disconnection. \endif

DisposeAsync Method

\if KO TCP 연결과 수신 루프 리소스를 비동기적으로 해제합니다. \endif \if EN Asynchronously releases the TCP connection and receive-loop resources. \endif \if KO 비동기 리소스 해제 작업입니다. \endif \if EN A value task representing asynchronous disposal. \endif

ReceiveLoopAsync Method

\if KO TCP 스트림에서 프레임을 계속 읽어 메시지로 디코딩하고 수신 이벤트를 발생시킵니다. \endif \if EN Continuously reads TCP frames, decodes messages, and raises receive events. \endif

cancellationToken— \if KO 수신 루프 종료 토큰입니다. \endif \if EN A token used to terminate the receive loop. \endif

반환: \if KO 백그라운드 수신 루프 작업입니다. \endif \if EN A task representing the background receive loop. \endif

SendAsync Method

\if KO 메시지를 외부 프로토콜과 프레임 형식으로 인코딩해 TCP 서버로 전송합니다. \endif \if EN Encodes a message using the external protocol and frame format and sends it to the TCP server. \endif

message— \if KO 전송할 메시지입니다. \endif \if EN The message to send. \endif
cancellationToken— \if KO 프레임 쓰기 취소 요청을 감시하는 토큰입니다. \endif \if EN A token used to observe frame-write cancellation. \endif

반환: \if KO 비동기 메시지 전송 작업입니다. \endif \if EN A task representing asynchronous message transmission. \endif

SetState Method

\if KO 원자적 연산으로 현재 연결 상태를 설정합니다. \endif \if EN Sets the connection state using an atomic operation. \endif

state— \if KO 저장할 새 상태입니다. \endif \if EN The new state to store. \endif
ValidateOptions Method

\if KO TCP 호스트, 포트, 버퍼 및 연결 제한 시간 설정을 검증합니다. \endif \if EN Validates TCP host, port, buffer, and connection-timeout options. \endif

options— \if KO 검증할 TCP 클라이언트 설정입니다. \endif \if EN The TCP client options to validate. \endif
Kind Property

\if KO TCP 전송 방식을 가져옵니다. \endif \if EN Gets the TCP transport kind. \endif

State Property

\if KO 스레드 안전하게 현재 TCP 연결 상태를 가져옵니다. \endif \if EN Gets the current TCP connection state in a thread-safe manner. \endif

_client Field

\if KO client 값을 보관합니다. \endif \if EN Stores the client value. \endif

_frameCodec Field

\if KO frame Codec 값을 보관합니다. \endif \if EN Stores the frame codec value. \endif

_options Field

\if KO options 값을 보관합니다. \endif \if EN Stores the options value. \endif

_protocolAdapter Field

\if KO protocol Adapter 값을 보관합니다. \endif \if EN Stores the protocol adapter value. \endif

_receiveLoopCts Field

\if KO receive Loop Cts 값을 보관합니다. \endif \if EN Stores the receive loop cts value. \endif

_receiveLoopTask Field

\if KO receive Loop Task 값을 보관합니다. \endif \if EN Stores the receive loop task value. \endif

_state Field

\if KO state 값을 보관합니다. \endif \if EN Stores the state value. \endif

MessageReceived Event

\if KO 완전한 TCP 프레임을 메시지로 디코딩했을 때 발생합니다. \endif \if EN Occurs when a complete TCP frame has been decoded into a message. \endif

TcpClientTransportOptions

ConnectTimeoutMs Property

\if KO 연결 제한 시간(밀리초)을 가져오거나 설정합니다. \endif \if EN Gets or sets the connection timeout in milliseconds. \endif

Host Property

\if KO 연결할 서버 호스트를 가져오거나 설정합니다. \endif \if EN Gets or sets the server host to connect to. \endif

Port Property

\if KO 연결할 서버 포트를 가져오거나 설정합니다. \endif \if EN Gets or sets the server port to connect to. \endif

ReceiveBufferSize Property

\if KO 수신 버퍼 크기(바이트)를 가져오거나 설정합니다. \endif \if EN Gets or sets the receive buffer size in bytes. \endif

SendBufferSize Property

\if KO 송신 버퍼 크기(바이트)를 가져오거나 설정합니다. \endif \if EN Gets or sets the send buffer size in bytes. \endif

TcpServerSendTargetMode

Broadcast Field

\if KO 연결된 모든 클라이언트에게 전송합니다. \endif \if EN Sends to every connected client. \endif

FirstClient Field

\if KO 가장 먼저 연결된 클라이언트에게만 전송합니다. \endif \if EN Sends only to the earliest connected client. \endif

LastClient Field

\if KO 가장 최근 연결된 클라이언트에게만 전송합니다. \endif \if EN Sends only to the most recently connected client. \endif

TcpServerTransport

#ctor Method

\if KO 기본 Dreamine JSON 프로토콜과 길이 접두사 프레임으로 TCP 서버를 초기화합니다. \endif \if EN Initializes the TCP server with the default Dreamine JSON protocol and length-prefixed framing. \endif

options— \if KO 수신 주소, 대기열, 버퍼 및 송신 대상 설정입니다. \endif \if EN The listen address, backlog, buffer, and send-target options. \endif
#ctor Method

\if KO TCP 서버 설정과 사용자 지정 프로토콜 및 프레임 코덱으로 서버를 초기화합니다. \endif \if EN Initializes the server with TCP options and custom protocol and frame codecs. \endif

options— \if KO 수신 주소, 대기열, 버퍼 및 송신 대상 설정입니다. \endif \if EN The listen address, backlog, buffer, and send-target options. \endif
protocolAdapter— \if KO 메시지와 외부 페이로드를 변환할 어댑터입니다. \endif \if EN The adapter that converts messages and external payloads. \endif
frameCodec— \if KO 클라이언트 스트림의 메시지 경계를 처리할 코덱입니다. \endif \if EN The codec that handles message boundaries in client streams. \endif
AcceptLoopAsync Method

\if KO TCP 클라이언트를 계속 수락하고 각 연결의 수신 루프를 시작합니다. \endif \if EN Continuously accepts TCP clients and starts a receive loop for each connection. \endif

cancellationToken— \if KO 수락 루프 종료 토큰입니다. \endif \if EN A token used to terminate the accept loop. \endif

반환: \if KO 백그라운드 수락 루프 작업입니다. \endif \if EN A task representing the background accept loop. \endif

BroadcastAsync Method

\if KO 연결된 모든 TCP 클라이언트에게 메시지를 병렬 전송합니다. \endif \if EN Sends a message in parallel to all connected TCP clients. \endif

message— \if KO 브로드캐스트할 메시지입니다. \endif \if EN The message to broadcast. \endif
cancellationToken— \if KO 브로드캐스트 취소 토큰입니다. \endif \if EN A token used to cancel broadcasting. \endif

반환: \if KO 비동기 브로드캐스트 작업입니다. \endif \if EN A task representing asynchronous broadcasting. \endif

CleanupClients Method

\if KO 현재 연결된 모든 클라이언트를 제거하고 해제합니다. \endif \if EN Removes and disposes all currently connected clients. \endif

CleanupListener Method

\if KO 정리 예외를 전파하지 않고 TCP Listener를 중지합니다. \endif \if EN Stops the TCP listener without propagating cleanup exceptions. \endif

ConnectAsync Method

\if KO TCP Listener를 시작하고 백그라운드 클라이언트 수락 루프를 실행합니다. \endif \if EN Starts the TCP listener and background client-accept loop. \endif

cancellationToken— \if KO 서버 및 수락 루프 수명과 연결할 취소 토큰입니다. \endif \if EN A cancellation token linked to server and accept-loop lifetime. \endif

반환: \if KO TCP 서버 시작 작업입니다. \endif \if EN A task representing TCP server startup. \endif

DisconnectAsync Method

\if KO 수락 루프와 Listener를 중지하고 연결된 모든 클라이언트를 해제합니다. \endif \if EN Stops the accept loop and listener and releases all connected clients. \endif

cancellationToken— \if KO 정리 후 연결 해제 취소 여부를 확인하는 토큰입니다. \endif \if EN A token checked for cancellation after cleanup. \endif

반환: \if KO 비동기 서버 종료 작업입니다. \endif \if EN A task representing asynchronous server shutdown. \endif

DisposeAsync Method

\if KO Listener, 수락 루프 및 클라이언트 연결을 비동기적으로 해제합니다. \endif \if EN Asynchronously releases the listener, accept loop, and client connections. \endif \if KO 비동기 리소스 해제 작업입니다. \endif \if EN A value task representing asynchronous disposal. \endif

GetTargetClients Method

\if KO 연결 시각과 대상 정책에 따라 송신 대상 클라이언트 스냅샷을 생성합니다. \endif \if EN Creates a target-client snapshot based on connection time and target policy. \endif

targetMode— \if KO 적용할 대상 선택 정책입니다. \endif \if EN The target-selection policy to apply. \endif

반환: \if KO 선택된 클라이언트 연결 배열입니다. \endif \if EN An array of selected client connections. \endif

NotifyConnectedClientCountChanged Method

\if KO 현재 연결 클라이언트 수로 변경 이벤트를 발생시킵니다. \endif \if EN Raises the count-change event with the current connected-client count. \endif

ParseHost Method

\if KO 서버 바인딩 호스트 문자열을 IPv4 주소로 변환합니다. \endif \if EN Parses a server bind-host string into an IPv4 address. \endif

host— \if KO 변환할 호스트 문자열입니다. \endif \if EN The host string to parse. \endif

반환: \if KO 바인딩에 사용할 IP 주소입니다. \endif \if EN The IP address to use for binding. \endif

ReceiveLoopAsync Method

\if KO 특정 클라이언트의 프레임을 계속 읽어 메시지 수신 이벤트를 발생시킵니다. \endif \if EN Continuously reads frames from one client and raises message-received events. \endif

clientId— \if KO 클라이언트 연결 식별자입니다. \endif \if EN The client connection identifier. \endif
client— \if KO 데이터를 읽을 TCP 클라이언트입니다. \endif \if EN The TCP client to read. \endif
cancellationToken— \if KO 수신 루프 종료 토큰입니다. \endif \if EN A token used to terminate the receive loop. \endif

반환: \if KO 클라이언트 수신 루프 작업입니다. \endif \if EN A task representing the client receive loop. \endif

RemoveClient Method

\if KO 연결 사전에서 클라이언트를 제거하고 소켓을 닫은 뒤 개수 변경을 알립니다. \endif \if EN Removes a client from the connection map, closes its socket, and reports the count change. \endif

clientId— \if KO 제거할 연결 식별자입니다. \endif \if EN The connection identifier to remove. \endif
client— \if KO 닫고 해제할 TCP 클라이언트입니다. \endif \if EN The TCP client to close and dispose. \endif
SendAsync Method

\if KO 구성된 기본 대상 정책에 따라 연결된 클라이언트에게 메시지를 전송합니다. \endif \if EN Sends a message to connected clients according to the configured target policy. \endif

message— \if KO 전송할 메시지입니다. \endif \if EN The message to send. \endif
cancellationToken— \if KO 송신 취소 요청을 감시하는 토큰입니다. \endif \if EN A token used to observe send cancellation. \endif

반환: \if KO 비동기 대상별 송신 작업입니다. \endif \if EN A task representing asynchronous targeted sending. \endif

SendAsync Method

\if KO 지정한 대상 정책으로 선택한 클라이언트들에게 메시지를 병렬 전송합니다. \endif \if EN Sends a message in parallel to clients selected by the specified target policy. \endif

targetMode— \if KO 클라이언트 선택 정책입니다. \endif \if EN The client-selection policy. \endif
message— \if KO 전송할 메시지입니다. \endif \if EN The message to send. \endif
cancellationToken— \if KO 모든 클라이언트 송신 취소 토큰입니다. \endif \if EN A token used to cancel all client sends. \endif

반환: \if KO 선택된 모든 클라이언트의 병렬 송신 작업입니다. \endif \if EN A task representing parallel sends to all selected clients. \endif

SendToClientAsync Method

\if KO 클라이언트별 잠금을 사용해 한 클라이언트에 프레임을 순차적으로 전송합니다. \endif \if EN Sends a frame sequentially to one client using its per-client lock. \endif

target— \if KO 대상 클라이언트 연결 정보입니다. \endif \if EN The target client connection. \endif
payload— \if KO 프레임으로 전송할 프로토콜 페이로드입니다. \endif \if EN The protocol payload to send as a frame. \endif
cancellationToken— \if KO 잠금 대기와 송신 취소 토큰입니다. \endif \if EN A token used to cancel lock waiting and sending. \endif

반환: \if KO 단일 클라이언트 송신 작업입니다. \endif \if EN A task representing the single-client send. \endif

SetState Method

\if KO 원자적 연산으로 현재 서버 상태를 설정합니다. \endif \if EN Sets the current server state using an atomic operation. \endif

state— \if KO 저장할 새 상태입니다. \endif \if EN The new state to store. \endif
ValidateOptions Method

\if KO TCP 서버 호스트, 포트, 대기열 및 버퍼 설정을 검증합니다. \endif \if EN Validates TCP server host, port, backlog, and buffer options. \endif

options— \if KO 검증할 TCP 서버 설정입니다. \endif \if EN The TCP server options to validate. \endif
ConnectedClientCount Property

\if KO 현재 서버에 연결된 TCP 클라이언트 수를 가져옵니다. \endif \if EN Gets the number of TCP clients currently connected to the server. \endif

Kind Property

\if KO TCP 전송 방식을 가져옵니다. \endif \if EN Gets the TCP transport kind. \endif

SendTargetMode Property

\if KO 기본 송신 작업에서 사용할 클라이언트 대상 정책을 가져오거나 설정합니다. \endif \if EN Gets or sets the client-target policy used by the default send operation. \endif

State Property

\if KO 스레드 안전하게 현재 서버 수신 대기 상태를 가져옵니다. \endif \if EN Gets the current server listen state in a thread-safe manner. \endif

_acceptLoopTask Field

\if KO accept Loop Task 값을 보관합니다. \endif \if EN Stores the accept loop task value. \endif

_clients Field

\if KO clients 값을 보관합니다. \endif \if EN Stores the clients value. \endif

_frameCodec Field

\if KO frame Codec 값을 보관합니다. \endif \if EN Stores the frame codec value. \endif

_listener Field

\if KO listener 값을 보관합니다. \endif \if EN Stores the listener value. \endif

_options Field

\if KO options 값을 보관합니다. \endif \if EN Stores the options value. \endif

_protocolAdapter Field

\if KO protocol Adapter 값을 보관합니다. \endif \if EN Stores the protocol adapter value. \endif

_serverCts Field

\if KO server Cts 값을 보관합니다. \endif \if EN Stores the server cts value. \endif

_state Field

\if KO state 값을 보관합니다. \endif \if EN Stores the state value. \endif

ConnectedClientCountChanged Event

\if KO 서버에 연결된 클라이언트 수가 변경될 때 발생합니다. \endif \if EN Occurs when the connected-client count changes. \endif

MessageReceived Event

\if KO 클라이언트 프레임을 메시지로 디코딩했을 때 발생합니다. \endif \if EN Occurs when a client frame has been decoded into a message. \endif

TcpServerTransportOptions

Backlog Property

\if KO 보류 연결 대기열의 최대 크기를 가져오거나 설정합니다. \endif \if EN Gets or sets the maximum pending-connection backlog. \endif

Host Property

\if KO 서버가 바인딩할 IP 주소를 가져오거나 설정합니다. 기본값은 모든 인터페이스입니다. \endif \if EN Gets or sets the IP address to bind; the default is all interfaces. \endif

Port Property

\if KO 서버가 수신 대기할 포트를 가져오거나 설정합니다. \endif \if EN Gets or sets the server listen port. \endif

ReceiveBufferSize Property

\if KO 클라이언트 수신 버퍼 크기(바이트)를 가져오거나 설정합니다. \endif \if EN Gets or sets the client receive buffer size in bytes. \endif

SendBufferSize Property

\if KO 클라이언트 송신 버퍼 크기(바이트)를 가져오거나 설정합니다. \endif \if EN Gets or sets the client send buffer size in bytes. \endif

SendTargetMode Property

\if KO 기본 메시지 송신 시 사용할 클라이언트 대상 정책을 가져오거나 설정합니다. \endif \if EN Gets or sets the client-target policy used by the default send operation. \endif

UdpTransport

#ctor Method

\if KO 기본 Dreamine JSON 프로토콜로 UDP 전송 계층을 초기화합니다. \endif \if EN Initializes UDP transport with the default Dreamine JSON protocol. \endif

options— \if KO 로컬·원격 엔드포인트와 소켓 설정입니다. \endif \if EN The local and remote endpoint and socket options. \endif
#ctor Method

\if KO UDP 설정과 사용자 지정 프로토콜 어댑터로 전송 계층을 초기화합니다. \endif \if EN Initializes UDP transport with options and a custom protocol adapter. \endif

options— \if KO 로컬·원격 엔드포인트와 소켓 설정입니다. \endif \if EN The local and remote endpoint and socket options. \endif
protocolAdapter— \if KO 메시지와 데이터그램 페이로드를 변환할 어댑터입니다. \endif \if EN The adapter that converts messages and datagram payloads. \endif
ConnectAsync Method

\if KO 로컬 엔드포인트에 UDP 소켓을 바인딩하고 백그라운드 수신 루프를 시작합니다. \endif \if EN Binds a UDP socket to the local endpoint and starts the background receive loop. \endif

cancellationToken— \if KO 연결 및 수신 루프 수명과 연결할 취소 토큰입니다. \endif \if EN A cancellation token linked to connection and receive-loop lifetime. \endif

반환: \if KO UDP 소켓 시작 작업입니다. \endif \if EN A task representing UDP socket startup. \endif

DisconnectAsync Method

\if KO UDP 소켓을 닫고 백그라운드 수신 루프를 종료합니다. \endif \if EN Closes the UDP socket and terminates the background receive loop. \endif

cancellationToken— \if KO 정리 후 연결 해제 취소 여부를 확인하는 토큰입니다. \endif \if EN A token checked for cancellation after cleanup. \endif

반환: \if KO 비동기 연결 해제 작업입니다. \endif \if EN A task representing asynchronous disconnection. \endif

DisposeAsync Method

\if KO UDP 소켓과 수신 루프 리소스를 비동기적으로 해제합니다. \endif \if EN Asynchronously releases the UDP socket and receive-loop resources. \endif \if KO 비동기 리소스 해제 작업입니다. \endif \if EN A value task representing asynchronous disposal. \endif

ReceiveLoopAsync Method

\if KO 데이터그램을 계속 수신해 메시지로 디코딩하고 수신 이벤트를 발생시킵니다. \endif \if EN Continuously receives datagrams, decodes messages, and raises receive events. \endif

cancellationToken— \if KO 수신 루프 종료 토큰입니다. \endif \if EN A token used to terminate the receive loop. \endif

반환: \if KO 백그라운드 수신 루프 작업입니다. \endif \if EN A task representing the background receive loop. \endif

SendAsync Method

\if KO 메시지를 프로토콜 페이로드로 인코딩해 구성된 원격 UDP 엔드포인트로 전송합니다. \endif \if EN Encodes a message as a protocol payload and sends it to the configured remote UDP endpoint. \endif

message— \if KO 전송할 메시지입니다. \endif \if EN The message to send. \endif
cancellationToken— \if KO 데이터그램 송신 취소 요청을 감시하는 토큰입니다. \endif \if EN A token used to observe datagram-send cancellation. \endif

반환: \if KO 비동기 데이터그램 송신 작업입니다. \endif \if EN A task representing asynchronous datagram transmission. \endif

SetState Method

\if KO 원자적 연산으로 현재 UDP 상태를 설정합니다. \endif \if EN Sets the current UDP state using an atomic operation. \endif

state— \if KO 저장할 새 상태입니다. \endif \if EN The new state to store. \endif
ValidateOptions Method

\if KO UDP 호스트, 포트 및 버퍼 설정을 검증합니다. \endif \if EN Validates UDP host, port, and buffer options. \endif

options— \if KO 검증할 UDP 설정입니다. \endif \if EN The UDP options to validate. \endif
ValidatePort Method

\if KO UDP 포트가 유효한 사용자 포트 범위인지 검증합니다. \endif \if EN Validates that a UDP port is within the valid user-port range. \endif

port— \if KO 검증할 포트 번호입니다. \endif \if EN The port number to validate. \endif
parameterName— \if KO 예외에 사용할 설정 이름입니다. \endif \if EN The option name used in the exception. \endif
Kind Property

\if KO UDP 전송 방식을 가져옵니다. \endif \if EN Gets the UDP transport kind. \endif

State Property

\if KO 스레드 안전하게 현재 UDP 소켓 상태를 가져옵니다. \endif \if EN Gets the current UDP socket state in a thread-safe manner. \endif

_client Field

\if KO client 값을 보관합니다. \endif \if EN Stores the client value. \endif

_options Field

\if KO options 값을 보관합니다. \endif \if EN Stores the options value. \endif

_protocolAdapter Field

\if KO protocol Adapter 값을 보관합니다. \endif \if EN Stores the protocol adapter value. \endif

_receiveLoopCts Field

\if KO receive Loop Cts 값을 보관합니다. \endif \if EN Stores the receive loop cts value. \endif

_receiveLoopTask Field

\if KO receive Loop Task 값을 보관합니다. \endif \if EN Stores the receive loop task value. \endif

_remoteEndPoint Field

\if KO remote End Point 값을 보관합니다. \endif \if EN Stores the remote end point value. \endif

_state Field

\if KO state 값을 보관합니다. \endif \if EN Stores the state value. \endif

MessageReceived Event

\if KO 수신 데이터그램을 메시지로 디코딩했을 때 발생합니다. \endif \if EN Occurs when a received datagram has been decoded into a message. \endif

UdpTransportOptions

CreateLocalEndPoint Method

\if KO 구성된 로컬 호스트와 포트에서 바인딩 엔드포인트를 생성합니다. \endif \if EN Creates a bind endpoint from the configured local host and port. \endif

반환: \if KO 로컬 UDP 엔드포인트입니다. \endif \if EN The local UDP endpoint. \endif

CreateRemoteEndPoint Method

\if KO 구성된 원격 호스트와 포트에서 송신 엔드포인트를 생성합니다. \endif \if EN Creates a send endpoint from the configured remote host and port. \endif

반환: \if KO 원격 UDP 엔드포인트입니다. \endif \if EN The remote UDP endpoint. \endif

ParseHost Method

\if KO 호스트 문자열을 IP 주소로 변환하고 필요 시 모든 인터페이스 주소를 허용합니다. \endif \if EN Parses a host string as an IP address and optionally permits the all-interfaces address. \endif

host— \if KO 변환할 호스트 문자열입니다. \endif \if EN The host string to parse. \endif
allowAny— \if KO 0.0.0.0을 모든 인터페이스로 허용할지 여부입니다. \endif \if EN Whether 0.0.0.0 is allowed as all interfaces. \endif

반환: \if KO 변환된 IP 주소입니다. \endif \if EN The parsed IP address. \endif

EnableBroadcast Property

\if KO 브로드캐스트 송신을 허용할지 여부를 가져오거나 설정합니다. \endif \if EN Gets or sets whether broadcast transmission is enabled. \endif

LocalHost Property

\if KO UDP 소켓이 바인딩할 로컬 호스트를 가져오거나 설정합니다. \endif \if EN Gets or sets the local host to which the UDP socket binds. \endif

LocalPort Property

\if KO UDP 소켓이 바인딩할 로컬 포트를 가져오거나 설정합니다. \endif \if EN Gets or sets the local UDP port. \endif

ReceiveBufferSize Property

\if KO 수신 버퍼 크기(바이트)를 가져오거나 설정합니다. \endif \if EN Gets or sets the receive buffer size in bytes. \endif

RemoteHost Property

\if KO UDP 메시지를 송신할 원격 호스트를 가져오거나 설정합니다. \endif \if EN Gets or sets the remote host for UDP messages. \endif

RemotePort Property

\if KO UDP 메시지를 송신할 원격 포트를 가져오거나 설정합니다. \endif \if EN Gets or sets the remote UDP port. \endif

ReuseAddress Property

\if KO 로컬 주소와 포트 재사용을 허용할지 여부를 가져오거나 설정합니다. \endif \if EN Gets or sets whether reuse of the local address and port is enabled. \endif

SendBufferSize Property

\if KO 송신 버퍼 크기(바이트)를 가져오거나 설정합니다. \endif \if EN Gets or sets the send buffer size in bytes. \endif