본 자료는
1. SmartTCPClient-Wrapping Class 소개
2. 사용자 수정 영역
3. SmartTCPClient-Wrapping Class 연결(Connect) 구조
4. SmartTCPClient-Wrapping Class 통신 구조
[CASE-1] 요청(Request/Send) and 응답(Response/Receive) 구성
[CASE-2] Server Event Data 수신
5. SmartTCPClient-Wrapping Class를 이용한 통신에러 확인
5-1. Connect 실패 유형에 따른 확인 항목
5-2. Send 실패 유형에 확인 항목
6. 예제 설명
6-1. 프로토콜
6-2. Client
6-3. Server
순서로 진행합니다.
TCP/IP Network Client 측 통신 프로그램 작성시 발생될 수 있는 여러가지 예외 처리 및 프로토콜에 의한 송수신시 필요한 처리를 별도로 작성할 수 있도록 만들어진 Wrapping Class를 제공하고있습니다. 따라서 개발자는 SmartTCPClient-Wrapping Class를 재사용하여 필요한 부분만을 수정 및 적용하므로 프로그램을 편리하게 작성할 수 있습니다. 개발자는 Wrapping Class 적용을 위하여 대부분 사용자 정의 영역의 코드를 재정의 및 수정하시면 됩니다. Wrapping Class는 SmartTCPClient Component를 기반으로 연동하여 동작 합니다.
[SmartTCPClient-Wrapping Class 특징]
1. 초기 Network 가용 상태 확인 기능
2. Connect 시 동기/비동기 지원
3. Connect 실패에 따른 재시도 처리 기능 지원
4. Connect 실패에 따른 Network 상 문제원인을 확인할 수 있는 기능 지원
5. 다양한 프로토콜 적용을 위한 사용자 정의 영역의 코드 지원
6. 요청(Request/Send) and 응답(Response/Receive) 확인 및 상태 값 리턴
7. Server로부터 수신되는 이벤트성 요청 수신 큐(Queue) 지원
본문을 확인하여 프로젝트에 SmartTCPClient-Wrapping Class를 적용해보시기 바라며, 적용이 어려우신 경우 원격으로 적용을 도와드리도록 하겠습니다.
2. 사용자 수정 영역SmartTCPClient-Wrapping Class는 크게 미리 정의된 영역과, 사용자가 코드를 수정해야 하는 사용자 정의 영역으로 나눌 수 있습니다. 사용자 정의 영역에서 상황 별 사용자가 수정해야 하는 메서드는 다음과 같습니다. 특히, Send, Receive 부분은 반드시 사용자의 프로토콜에 맞도록 코드를 작성해야 합니다.
- ※ Connect 동작 관련
-
인터페이스 void ConnectRetryFail_User(NetworkConnectStatus eNetworkStatus) 권장동작 최종적으로 Connect에 실패 한 경우 NetworkConnectStatus 열거값에 따라 Connect 재시도 또는 Connect 실패 원인을 사용자에게 알리는 처리를 하도록 작성합니다. 현재 동작 ConnectMaxRetryCount로 지정한 횟수 만큼 Connect를 시도했으나, 서버와 연결에 실패한 경우 호출되며, 인자값으로 전달받은 네트워크 상태에 따라 Connect를 재시도 하거나, 네트워크 상태에 따른 처리 방법을 메시지 박스에 출력합니다.
- ※ Send (Request-Response) 동작 관련
-
인터페이스 Data_Packet Command_RequestResponse(string strCommand, int iCh, byte[] chData) 권장동작 사용하는 프로토콜에 따라 인자 형식을 변경하고, Request 결과(SendStatus)에 따라 Response 수신 처리 작성과, Request 실패 처리를 작성합니다. 현재 동작 Server로 Command에 따른 데이터 전송(Request) 후 Server 의 응답(Response)을 수신받을 때까지 대기하고 Request-Response 과정의 결과(CommandStatus)를 리턴 하도록 처리함 인터페이스 SendStatus Request_Command(string strCommand, int iCh, byte[] chData) 권장동작 사용하는 프로토콜에 맞게 인자 형식을 변경하고 프레임을 구성하여 Server로 Request 전송 처리하는 과정을 작성합니다. 현재 동작 예제 프로토콜에 맞도록 프레임 구성 후 Server로 데이터를 전송(Request)하고, 데이터 전송 상태(SendStatus)를 리턴 하도록 처리함 인터페이스 Data_Packet Response_Parsing(byte[] chData, bool bAckRecv) 권장동작 수신받은 Response 데이터나 Server에서 임의의 시점에 수신받은 데이터(Server Event Data)를 사용하는 프로토콜에 맞게 검증 후 파싱하여 구조체 데이터에 저장하는 과정을 작성합니다. 현재 동작 Request 후 Server로부터 응답(Response)받거나, 임의의 시점에 수신받은(Server Event Data) 데이터를 사용자의 프로토콜에 맞게 검증 및 파싱 후 데이터 패킷(Data_Packet)을 구성하여 (채워넣어) 리턴 하도록 처리함 인터페이스 void ACK_OnReceiveHandler_User(byte[] receiveData) 권장동작 Request 전송 후 올바르게 Response 수신 받았을 때의 처리를 작성합니다. Response 수신 완료 처리 및 사용자의 프로토콜에 맞게 처리 코드를 작성합니다. 현재 동작 현재 코드는 공란입니다.
※ 특별한 경우가 아니라면 사용하지 않습니다.
- ※ Receive (Sever Event Send) 동작 관련
-
인터페이스 void OnReceiveHandler_User(byte[] receiveData) 권장동작 서버에서 임의의 시점에 데이터(Server Event Data)를 수신 받았을 때의 처리를 작성합니다.
Server Event Data 수신 알림 및 사용자의 프로토콜에 맞게 처리 코드를 작성합니다.현재 동작 현재 코드는 공란입니다.
※ 특별한 경우가 아니라면 사용하지 않습니다.
SmartTCPClient-Wrapping Class는 네트워크 체크를 위해 SmartConfigs 컴포넌트를 이용하여 Ping 통신을 진행합니다. 이때 사용하는 SmartConfigs는 생성자에서 생성 또는 참조를 받게 됩니다. 따라서 생성자는 2가지가 존재하며 인자값에 따른 생성자의 차이점 및 사용시점은 다음과 같습니다.
생성자 | CSmartTCPClientWrapping | |
---|---|---|
인자값 |
SmartTCPClient pSmartTCPClient |
SmartTCPClient pSmartTCPClient, SmartConfigs pSmartConfig |
차이점 |
클래스 내부에 SmartConfigs를 생성함 |
메인 프로젝트의 SmartConfigs 컴포넌트의 참조를 전달받음 |
사용시점 |
메인 프로젝트에서 SmartConfigs 컴포넌트를 사용하지 않음 |
메인 프로젝트에서 SmartConfigs 컴포넌트를 사용함 |
SmartTCPClient-Wrapping Class에서 연결 방식은 동기/비동기 방식이 있으며, Connect 실패 시 재시도 회수와 간격을 설정할 수 있습니다. 또한 Network 상태를 확인하는 기능을 이용하여 현재 Network가 가용 상태인지 확인할 수 있습니다. 서버 연결 구조는 아래 그림과 같습니다.
서버와 연결에 실패한 경우 ConnectRetryFail_User() 메서드는 Network_Check() 메서드로부터 연결실패 원인을 인자값으로 전달받아 호출됩니다.
예제의 ConnectRetryFail_User() 메서드 코드는 연결실패 원인에 따른 처리 사항을 메시지박스로 출력하게
되어있으며, 다르게 처리하려는 경우 직접 코드를 수정하여 적용하시기 바랍니다.
서버와 연결에 실패한 경우 ConnectRetryFail_User() 메서드는 Network_Check() 메서드로부터 연결실패
원인을 인자값으로 전달받아 호출됩니다.
예제의 ConnectRetryFail_User() 메서드 코드는 연결실패 원인에 따른 처리 사항을 메시지박스로 출력하게
되어있으며, 다르게 처리하려는 경우 직접 코드를 수정하여 적용하시기 바랍니다.
※ 메서드(함수) | |
---|---|
인터페이스명 | ConnectRetryFail_User |
설명 |
ConnectMaxRetryCount로 지정한 횟수 만큼 Connect를 시도했으나, 서버와 연결에 실패한
경우 호출되는 메서드로, 인자값으로 전달받은 네트워크 상태에 따라 Connect를 재시도
하거나, Connect를 중단하도록 하는 메서드 [NetworkConnectStatus 인자 값] • Available : 서버와 연결 가능한 상태 • NetworkDeviceProblems : 네트워크 장비(공유기, 허브) 문제 발생. Ping 통신 실패 • ServerProblems : 서버 확인. Ping 통신 실패 • ServerProcessProblems : 서버 프로그램 확인. Ping 통신은 성공했으나, Connect 에 실패함 ⊙ void ConnectRetryFail_User(NetworkConnectStatus eNetworkStatus) |
명칭 | 리턴값 | 설명 |
---|---|---|
Connect RetryTimer_ Tick |
void (Event Method) |
Connect 재시도 타이머 |
smartTCPClient_ OnConnected |
void (Event Method) |
연결방식이 비동기 방식인 경우, 연결상태 확인 이벤트 |
Connect RetryTimer_ Tick |
void (Event Method) |
Connect 재시도 타이머 |
Network_ Check |
Network Connect Status |
통신에러 원인을 확인 |
IPAddress Available Check |
bool | 공유기(허브) 연결 확인 : Ping 체크 후 결과를 리턴합니다. |
Server Available Check |
bool | 서버 연결 확인 : Ping 체크 후 결과를 리턴합니다. 단, 서버에서 Ping 을 막은 경우 확인 불가 |
Server Process Check |
bool | 서버 프로그램 확인 : Connect 체크 |
Connect ReTry |
void | Connect 재시도 |
※ 프로퍼티(속성) | |
---|---|
인터페이스명 | IsNetworkAvailable |
설명 |
공유기(허브)의 연결상태를 체크 • IPAddressAvailableCheck() 의 리턴값을 반환합니다. |
인터페이스명 | ConnectMaxRetryCount |
---|---|
설명 | 연결 재시도 횟수를 설정 |
인터페이스명 | ConnectRetryInterval |
---|---|
설명 | 연결 재시도 간격을 설정 |
인터페이스명 | Synchronous_Connect |
---|---|
설명 | 서버 연결 모드를 설정(동기, 비동기) |
인터페이스명 | Synchronous_Receive |
---|---|
설명 | 서버 수신 모드를 설정(동기, 비동기) |
인터페이스명 | NetworkDeviceIP |
---|---|
설명 | 공유기(허브) IP를 설정 |
인터페이스명 | ServerAddress |
---|---|
설명 | 서버 IP를 설정 |
인터페이스명 | IsConnected |
---|---|
설명 |
서버와 연결 상태를 확인 [ConnectionStatus 리턴 값] • Connected: 서버와 연결됨 • DisConnected: 서버와 연결이 해제됨 • Connecting: 서버와 연결중인 상태 |
※ 메서드(함수) | |
---|---|
인터페이스명 | Connect |
설명 |
서버와 연결을 시도합니다 . ⊙ void Connect(int iPort, int iTimeoutInterval) |
인터페이스명 | Disconnect |
---|---|
설명 |
서버와 연결을 해제 합니다 . ⊙ void Disconnect() |
SmartTCPClient-Wrapping Classs에서 기본적인 통신 구조는 두가지 모델을 지원하고있습니다.
요청-응답(Request-Response)구조는 Client에서 Server로 데이터를 요청하면 Server는 반드시 Client로 응답을 전송해야 하는 구조로, 송/수신 구조는 아래 그림과 같습니다.
Command_RequestResponse() 메서드는 사용자의 프로토콜에 따른 Request-Response 동작을 하는 메서드로,
내부에서 Request_Command() 메서드를 호출하여 서버로 프로토콜에 따른 Request 프레임 전송 후 미리 정의
된 상수 ACKTIMEOUT 시간동안 서버의 Response 프레임 수신을 대기하며 Command_RequestResponse()
메서드로 데이터 전송 상태를 리턴합니다.
서버로부터 Response 프레임이 수신되었다면, ACK_OnReceiveHandler_User() 메서드가 호출되어 사용자가
원하는 처리를 할 수 있습니다.
또한 Command_RequestResponse() 메서드 내부에서 Response_Parsing()
메서드가 호출되어 수신받은 Response 프레임을 프로토콜에 맞게 파싱(Parsing)작업을 진행합니다.
따라서 사용자는 Command_RequestResponse(),Request_Command(),Response_Parsing() 메서드의 코드를
사용자의 프로토콜에 맞도록 수정하는 작업이 반드시 필요합니다.
※ 메서드(함수) | |
---|---|
인터페이스명 | Request_Command |
설명 |
사용자의 프로토콜에 맞는 프레임 구성 후 Server로 데이터를 전송하고, 데이터 전송
상태(SendStatus)를 리턴하는 메서드 [SendStatus 리턴 값] • Success : 데이터 전송 후 서버로부터 응답을 받음 • ConnectionFailed : 서버와 연결되지 않음 • SendFailed : 데이터 전송에 실패 (Send관련 메서드에서 False리턴) • AckFailed : 데이터 전송에 성공했으나, 서버로부터 응답이 오지 않음 ⊙ SendStatus Request_Command(string strCommand, int iCh, byte[] chData) |
인터페이스명 | Response_Parsing |
---|---|
설명 |
Request 후 Server로부터 응답(Response)받거나, 임의의 시점에 수신받은 (Server Event
Data) 데이터를 사용자의 프로토콜에 맞게 검증 및 파싱 후 데이터 패킷(Data_Packet)을
구성하여 리턴하는 메서드 [Data_Packet 구조체 멤버] • public byte[] chCommand: 송수신한 Command를 저장 • public byte chChannel: 송수신한 Channel을 저장 • public byte[] chData: 송수신한 Data를 저장 • public CommandStatus chCommandStatus: 수신받은 데이터의 상태를 저장 ⊙ Data_Packet Response_Parsing(byte[] chData, bool bAckRecv) |
인터페이스명 | ACK_OnReceiveHandler_User |
---|---|
설명 |
서버로 Request 후 정상적으로Response 받은 경우 발생하는 메서드 ⊙ void ACK_OnReceiveHandler_User(byte[] receiveData) |
※ 메서드(함수) | |
---|---|
인터페이스명 | Command_RequestResponse |
설명 |
Server로 Command에 따른 데이터 전송(Request) 후 Server 의 응답(Response)을
수신받을 때까지 대기하고 Request-Response 과정의 결과(CommandStatus)를 리턴하는
메서드 [Data_Packet 구조체 멤버] • public byte[] chCommand : 송수신한 Command를 저장 • public byte chChannel : 송수신한 Channel을 저장 • public byte[] chData : 송수신한 Data를 저장 • public CommandStatus chCommandStatus : 수신받은 데이터의 상태를 저장 ⊙ Data_Packet Command_RequestResponse(string strCommand, int iCh, byte[] chData) |
명칭 | 리턴값 | 설명 |
---|---|---|
SmartTCPClient_SendData() | bool | 실제 Server로 데이터를 전송하는 메서드로 데이터 전송 후 ACK 응답 (Response)이 수신될 때 까지 대기 합니다. |
SmartTCPClient_OnReceiveHandler() | void (Event Method) |
Server로부터 데이터를 수신받을 때 발생하는 이벤트로 수신받은 데이터를 List에 저장하고 ACK응답 수신성공 처리를 합니다. |
※ 메서드(함수) | |
---|---|
인터페이스명 | SendData |
설명 |
Server로 데이터 전송 후 전송 상태를 리턴합니다. [SendStatus 리턴 값] • Success : 데이터 전송 후 서버로부터 응답을 받음 • ConnectionFailed : 서버와 연결되지 않음 • SendFailed : 데이터 전송에 실패 (Send관련 메서드에서 False리턴) • AckFailed : 데이터 전송에 성공했으나, 서버로부터 응답이 오지 않음 ⊙ SendStatus SendData(byte[] sendData) |
Client의 Request 전송과 관계없이 Server로부터 임의의 시점에 데이터를 수신받는 경우이며, 수신 구조는 아래 그림과 같습니다.
서버로부터 임의의 시점에 데이터가 수신되면 OnReceiveHandler_User() 메서드가 호출되어 사용자가 원하는
처리를 할 수 있으며, 수신받은 데이터는 Response_Parsing() 메서드에서 사용자의 프로토콜에 맞게 파싱되어
Data Queue인 m_EventResponsePacket 에 저장(Enqueue)됩니다.
사용자는 GetServerEventReceiveQueueCount
프로퍼티(속성)을 확인하여 Queue에 데이터가 있다면 GetServerEventReceiveQueue() 메서드를 호출하여
수신받은 데이터를 가져올(Dequeue) 수 있습니다.
명칭 | 자료형 | 설명 |
---|---|---|
m_EventResponsePacket | Data_Packet | 서버에서 임의로 송신한 데이터를 저장할 Queue |
SmartTCPClient_OnReceiveHandler() | void (Event Method) |
Server로부터 데이터를 수신받을 때 발생하는 이벤트로 수신받은 데이터를 List에 저장하고 ACK응답 수신성공 처리를 합니다. |
※ 메서드(함수) | |
---|---|
인터페이스명 | OnReceiveHandler_User |
설명 |
Server로부터 임의의 시점에 데이터가 수신될 경우 발생하는 메서드(Server Event Data 처리) ⊙ void OnReceiveHandler_User(byte[] receiveData) |
인터페이스명 | Response_Parsing |
---|---|
설명 |
Request 후 Server로부터 응답(Response)받거나, 임의의 시점에 수신받은 (Server Event
Data) 데이터를 사용자의 프로토콜에 맞게 검증 및 파싱 후 데이터 패킷(Data_Packet)을
구성하여 리턴하는 메서드 [Data_Packet 구조체 멤버] • public byte[] chCommand: 송수신한 Command를 저장 • public byte chChannel: 송수신한 Channel을 저장 • public byte[] chData: 송수신한 Data를 저장 • public CommandStatus chCommandStatus: 수신받은 데이터의 상태를 저장 ⊙ Data_Packet Response_Parsing(byte[] chData, bool bAckRecv) |
※ 프로퍼티(속성) | |
---|---|
인터페이스명 | GetServerEventReceiveQueueCount |
설명 | Queue에 저장된 패킷의 수를 읽습니다. |
※ 메서드(함수) | |
---|---|
인터페이스명 | GetServerEventReceiveQueue |
설명 |
Queue에 저장된 패킷을 가져옵니다.(Dequeue) [Data_Packet 구조체 멤버] • public byte[] chCommand: 송수신한 Command를 저장 • public byte chChannel: 송수신한 Channel을 저장 • public byte[] chData: 송수신한 Data를 저장 • public CommandStatus chCommandStatus: 수신받은 데이터의 상태를 저장 ⊙ Data_Packet GetServerEventReceiveQueue() |
명칭 | 자료형 | 설명 |
---|---|---|
SmartTCPClient_OnReceiveHandler() | void (Event Method) |
Server로부터 데이터를 수신받을 때 발생하는 이벤트로 수신받은 데이터를 Queue에 저장 (Enqueue)하고, 사용자 처리 메서드를 발생시킵니다. |
5. SmartTCPClient-Wrapping Class를 이용한 통신에러 확인
TCP/IP 통신 중 다양한 통신 에러가 발생할 수 있으며 유형에 따른 확인 항목을 안내합니다.
네트워크가 연결되지 않는 경우에는 “커뮤니티 → 자주하는 질문 → 32. 네트워크가 연결이 되지 않을 때 점검 사항” 내용을 참조하시기 바랍니다.
Connect 실패 시 ConnectRetryFail_User() 메서드의 인자값을 확인하여 통신 에러 원인을 파악할 수 있습니다.
[표] NetworkConnectStatus 열거값에 따른 확인 항목
리턴값 | 확인 항목 |
---|---|
NetworkDeviceProblems | 공유기의 상태와, 단선되지 않았는지 확인 |
ServerProblems | 서버로 Ping 통신이 되지 않음. 서버가 네트워크에 연결이 되어있는지 확인 |
ServerProcessProblems | 서버로 Ping 통신이 되어 네트워크는 정상이지만, 서버 프로그램이 정상적으로 동작하는지 확인 |
Send_Data(), Command_RequestResponse() 메서드 호출 후 또는 이벤트 데이터 수신 Queue의 SendStatus 또는 CommandStatus 열거값을 확인하여 통신 에러 원인을 파악할 수 있습니다.
[표2] SendStatus / CommandStatus 열거값에 따른 확인 항목
리턴값 | 확인 항목 |
---|---|
ConnectionFailed | 서버와 연결되지 않음. 서버 연결 후 전송 시도 |
SendFailed | 데이터 전송에 실패. 네트워크 장비 이상 여부와 케이블이 단선되었는지 확인 |
AckFailed | 데이터 전송에 성공했으나, 서버로부터 응답이 오지 않음. 서버 프로그램 확인 |
CommandInvalid | 수신받은 Command가 잘못됨. 서버 프로그램 확인 |
DataInvalid | 수신받은 데이터가 잘못됨. 서버 프로그램 확인 |
예제에 사용된 프로토콜은 Request-Response 통신구조로, Command는 총 8개가 있으며 Channel은 4Ch로 구성되어 있습니다. Data는 Binary 데이터이며 나머지 항목은 ASCII 데이터 입니다.
[Command 코드에 따른 Request 프레임 구조 ]
CMD 코드 |
STX (1Byte) |
CMD (3Byte) |
Channel (1Byte) |
Data | ETX (1Byte) |
||
---|---|---|---|---|---|---|---|
온도읽기 (TMR) |
0x40 | 0x54 | 0x4D | 0x52 | 0Ch : 0x30 1Ch : 0x31 2Ch : 0x32 3Ch : 0x33 |
None | 0x3B |
온도쓰기 (TMW) |
0x54 | 0x4D | 0x57 | 4Byte | |||
습도읽기 (HMR) |
0x48 | 0x4D | 0x52 | None | |||
습도쓰기 (HMW) |
0x48 | 0x4D | 0x57 | 4Byte | |||
수위읽기 (WTR) |
0x57 | 0x54 | 0x52 | None | |||
수위쓰기 (WTW) |
0x57 | 0x54 | 0x52 | 4Byte | |||
거리읽기 (DTR) |
0x44 | 0x54 | 0x52 | None | |||
거리쓰기 (DTW) |
0x44 | 0x54 | 0x57 | 4Byte |
[Sever의 Command별 Response 또는 Event Send 프레임 구조
CMD 코드 |
STX (1Byte) |
CMD (3Byte) |
Channel (1Byte) |
Data (4Byte) |
ETX (1Byte) |
||
---|---|---|---|---|---|---|---|
온도읽기 (TMR) |
0x40 | 0x54 | 0x4D | 0x52 | 0Ch : 0x30 1Ch : 0x31 2Ch : 0x32 3Ch : 0x33 |
Response or Event Data |
0x3B |
온도쓰기 (TMW) |
0x54 | 0x4D | 0x57 | ||||
습도읽기 (HMR) |
0x48 | 0x4D | 0x52 | ||||
습도쓰기 (HMW) |
0x48 | 0x4D | 0x57 | ||||
수위읽기 (WTR) |
0x57 | 0x54 | 0x52 | ||||
수위쓰기 (WTW) |
0x57 | 0x54 | 0x52 | ||||
거리읽기 (DTR) |
0x44 | 0x54 | 0x52 | ||||
거리쓰기 (DTW) |
0x44 | 0x54 | 0x57 |
SmartTCPClient-Wrapping Class 예제 프로그램의 동작 순서(구조)는 다음과 같습니다.
1. 프로그램 시작시 IsNetworkAvailable 속성으로 네트워크 디바이스(공유기, 허브)와 연결상태를 확인
2. 네트워크 사용이 가능한 경우 Connect() 메서드를 호출하여 서버와 연결하거나 Disconnect() 메서드를
호출하여 서버와 연결을 해제한다.
3. 서버로 Command에 따른 데이터를 Request 한다.
(Send_Data() 또는 Command_RequestResponse() 메서드 호출)
4. Request 후 서버로부터 Response 응답을 받는다.(ACK_OnReceiveHandler_User() 메서드 발생)
5. 서버에서 임의로 송신한 Event Data를 수신한다.
(m_EventResponsePacket Queue에 데이터 추가 및 OnReceiveHandler_User() 메서드 발생)
6. Queue의 데이터를 확인하여 Dequeue 한다.
(GetServerEventReceiveQueueCount 속성 및 GetServerEventReceiveQueue() 메서드 호출)
SmartTCPMultiServer를 이용한 예제 프로그램의 동작 순서(구조)는 다음과 같습니다.
1. Start() 메서드를 호출하여 Server를 Open 합니다.
2. smartTCPMultiServer1_OnReceiveHandler 이벤트에서 Request 데이터 수신 후 파싱하여 Response 데이터를
전송합니다.
3. Client로 임의의 시점에 Event Data를 전송합니다.