102 lines
3.3 KiB
C
102 lines
3.3 KiB
C
#include "c_TcpPollReactor.h"
|
|||
|
|
#include "c_Test.h"
|
||
|
|
#include "c_TcpServer.h"
|
||
|
|
|
||
|
|
|
||
|
|
static int g_tracking_counter = 0;
|
||
|
|
|
||
|
|
static bool OnConnectHandler(c_socket_t s, const c_SockAddr_t* addr, void* args) {
|
||
|
|
(void)addr; (void)args;
|
||
|
|
g_tracking_counter = 10;
|
||
|
|
|
||
|
|
char ip_buffer[NI_MAXHOST];
|
||
|
|
char port_buffer[NI_MAXSERV];
|
||
|
|
|
||
|
|
// 3. 将二进制地址转换为明文的 IP 和 端口字符串
|
||
|
|
// NI_NUMERICHOST: 以数字形式返回 IP
|
||
|
|
// NI_NUMERICSERV: 以数字形式返回端口号(而不是服务名如 http/ftp)
|
||
|
|
c_err_t err = c_SocketUtil_GetNameInfoForSocket(s, ip_buffer, NI_MAXHOST, port_buffer, NI_MAXSERV);
|
||
|
|
|
||
|
|
if (err == 0) {
|
||
|
|
printf("Connect from IP:PORT %s:%s\n", ip_buffer, port_buffer);
|
||
|
|
}
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
static bool OnDataHandler(c_socket_t s, void* args) {
|
||
|
|
(void)s; (void)args;
|
||
|
|
|
||
|
|
char ip_buffer[NI_MAXHOST];
|
||
|
|
char port_buffer[NI_MAXSERV];
|
||
|
|
|
||
|
|
// 3. 将二进制地址转换为明文的 IP 和 端口字符串
|
||
|
|
// NI_NUMERICHOST: 以数字形式返回 IP
|
||
|
|
// NI_NUMERICSERV: 以数字形式返回端口号(而不是服务名如 http/ftp)
|
||
|
|
c_err_t err = c_SocketUtil_GetNameInfoForSocket(s, ip_buffer, NI_MAXHOST, port_buffer, NI_MAXSERV);
|
||
|
|
|
||
|
|
if (err == 0) {
|
||
|
|
printf("Receive data from IP:PORT %s:%s\n", ip_buffer, port_buffer);
|
||
|
|
}
|
||
|
|
|
||
|
|
return false; /* Instantly signal termination to verify disconnect loops */
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Disconnect handler callback matching your exact specification naming format */
|
||
|
|
static void OnDisconnectHandler(c_socket_t s, void* args) {
|
||
|
|
(void)s; (void)args;
|
||
|
|
g_tracking_counter = 0; /* Clear metrics register */
|
||
|
|
|
||
|
|
char ip_buffer[NI_MAXHOST];
|
||
|
|
char port_buffer[NI_MAXSERV];
|
||
|
|
|
||
|
|
// 3. 将二进制地址转换为明文的 IP 和 端口字符串
|
||
|
|
// NI_NUMERICHOST: 以数字形式返回 IP
|
||
|
|
// NI_NUMERICSERV: 以数字形式返回端口号(而不是服务名如 http/ftp)
|
||
|
|
c_err_t err = c_SocketUtil_GetNameInfoForSocket(s, ip_buffer, NI_MAXHOST, port_buffer, NI_MAXSERV);
|
||
|
|
|
||
|
|
if (err == 0) {
|
||
|
|
printf("Client Closed IP:PORT %s:%s\n", ip_buffer, port_buffer);
|
||
|
|
} else {
|
||
|
|
fprintf(stderr, "getnameinfo 失败: %s\n", gai_strerror(c_Socket_GetErrno()));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST_CASE(test_multiplex_reactor_server_polling) {
|
||
|
|
c_Socket_Init();
|
||
|
|
|
||
|
|
c_TcpServer_t server;
|
||
|
|
c_err_t err = c_TcpServer_Init(&server, AF_INET, 8888, 512, NULL);
|
||
|
|
ASSERT_INT_EQ(C_SUCCESS, err);
|
||
|
|
|
||
|
|
/* Hook callbacks using the realigned layout names */
|
||
|
|
c_TcpServer_SetCallbacks(&server, OnConnectHandler, OnDataHandler, OnDisconnectHandler);
|
||
|
|
|
||
|
|
|
||
|
|
/* 1. Instantiate the poll driver subclass instance */
|
||
|
|
c_TcpReactor_t* poll_backend = NULL;
|
||
|
|
err = c_TcpPollReactor_Create(&poll_backend, &server.allocator);
|
||
|
|
ASSERT_INT_EQ(C_SUCCESS, err);
|
||
|
|
|
||
|
|
/* 2. Bind the engine onto the polymorphic execution loop layer */
|
||
|
|
err = c_TcpServer_SetReactor(&server, poll_backend);
|
||
|
|
ASSERT_INT_EQ(C_SUCCESS, err);
|
||
|
|
|
||
|
|
/* 3. Execute a non-blocking test loop pass with a quick 50ms timeout threshold */
|
||
|
|
while (server.is_running) {
|
||
|
|
err = c_TcpServer_Run(&server, 60000, NULL);
|
||
|
|
ASSERT_INT_EQ(C_SUCCESS, err);
|
||
|
|
}
|
||
|
|
|
||
|
|
c_TcpServer_Destroy(&server);
|
||
|
|
c_Socket_Destroy();
|
||
|
|
}
|
||
|
|
|
||
|
|
int main(void) {
|
||
|
|
TEST_START(TcpServer_MultiplexReactor_Suite);
|
||
|
|
RUN_TEST(test_multiplex_reactor_server_polling);
|
||
|
|
TEST_REPORT();
|
||
|
|
RETURN_TEST_STATUS;
|
||
|
|
}
|
||
|
|
|