fix: #71 Development of a simple Linux Client

This commit is contained in:
yuanyuanxiang
2025-04-06 19:35:20 +08:00
parent 9475e59887
commit 7a6b57917a
31 changed files with 629 additions and 124 deletions

View File

@@ -1,10 +1,22 @@
// IOCPClient.cpp: implementation of the IOCPClient class.
//
//////////////////////////////////////////////////////////////////////
#ifdef _WIN32
#include "stdafx.h"
#else
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netinet/in.h> // For struct sockaddr_in
#include <unistd.h> // For close()
#include <cstring> // For memset()
inline int WSAGetLastError() { return -1; }
#define USING_COMPRESS 1
#endif
#include "IOCPClient.h"
#include <IOSTREAM>
#include <assert.h>
#include <string>
#if USING_ZLIB
#include "zlib/zlib.h"
#define Z_FAILED(p) (Z_OK != (p))
@@ -36,26 +48,60 @@
#endif
#endif
#endif
#include <assert.h>
#include "Manager.h"
using namespace std;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
VOID IOCPClient::setManagerCallBack(CManager* Manager)
#ifndef _WIN32
BOOL SetKeepAliveOptions(int socket, int nKeepAliveSec = 180) {
// <20><><EFBFBD><EFBFBD> TCP <20><><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1>
int enable = 1;
if (setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable)) < 0) {
std::cerr << "Failed to enable TCP keep-alive" << std::endl;
return FALSE;
}
// <20><><EFBFBD><EFBFBD> TCP_KEEPIDLE (3<><33><EFBFBD>ӿ<EFBFBD><D3BF>к<EFBFBD><D0BA><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD> keep-alive <20><>)
if (setsockopt(socket, IPPROTO_TCP, TCP_KEEPIDLE, &nKeepAliveSec, sizeof(nKeepAliveSec)) < 0) {
std::cerr << "Failed to set TCP_KEEPIDLE" << std::endl;
return FALSE;
}
// <20><><EFBFBD><EFBFBD> TCP_KEEPINTVL (5<><35><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><D4BC><EFBFBD>)
int keepAliveInterval = 5; // 5<><35>
if (setsockopt(socket, IPPROTO_TCP, TCP_KEEPINTVL, &keepAliveInterval, sizeof(keepAliveInterval)) < 0) {
std::cerr << "Failed to set TCP_KEEPINTVL" << std::endl;
return FALSE;
}
// <20><><EFBFBD><EFBFBD> TCP_KEEPCNT (<28><><EFBFBD><EFBFBD>5<EFBFBD><35>̽<EFBFBD><CCBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD>ӶϿ<D3B6>)
int keepAliveProbes = 5;
if (setsockopt(socket, IPPROTO_TCP, TCP_KEEPCNT, &keepAliveProbes, sizeof(keepAliveProbes)) < 0) {
std::cerr << "Failed to set TCP_KEEPCNT" << std::endl;
return FALSE;
}
std::cout << "TCP keep-alive settings applied successfully" << std::endl;
return TRUE;
}
#endif
VOID IOCPClient::setManagerCallBack(void* Manager, DataProcessCB dataProcess)
{
m_Manager = Manager;
m_DataProcess = dataProcess;
}
IOCPClient::IOCPClient(bool exit_while_disconnect)
IOCPClient::IOCPClient(BOOL &bExit, bool exit_while_disconnect) : g_bExit(bExit)
{
m_Manager = NULL;
#ifdef _WIN32
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif
m_sClientSocket = INVALID_SOCKET;
m_hWorkThread = NULL;
@@ -67,7 +113,6 @@ IOCPClient::IOCPClient(bool exit_while_disconnect)
m_bIsRunning = TRUE;
m_bConnected = FALSE;
InitializeCriticalSection(&m_cs);
m_exit_while_disconnect = exit_while_disconnect;
#if USING_CTX
m_Cctx = ZSTD_createCCtx();
@@ -92,13 +137,13 @@ IOCPClient::~IOCPClient()
m_hWorkThread = NULL;
}
#ifdef _WIN32
WSACleanup();
#endif
while (S_RUN == m_bWorkThread)
Sleep(10);
DeleteCriticalSection(&m_cs);
m_bWorkThread = S_END;
#if USING_CTX
ZSTD_freeCCtx(m_Cctx);
@@ -107,8 +152,9 @@ IOCPClient::~IOCPClient()
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡIP<49><50>ַ
inline string GetIPAddress(const char *hostName)
inline std::string GetIPAddress(const char *hostName)
{
#ifdef _WIN32
struct hostent *host = gethostbyname(hostName);
#ifdef _DEBUG
Mprintf("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IP<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ: %s.\n", host->h_addrtype == AF_INET ? "IPV4" : "IPV6");
@@ -118,6 +164,27 @@ inline string GetIPAddress(const char *hostName)
if (host == NULL || host->h_addr_list == NULL)
return "";
return host->h_addr_list[0] ? inet_ntoa(*(struct in_addr*)host->h_addr_list[0]) : "";
#else
struct addrinfo hints, * res;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET; // IPv4
hints.ai_socktype = SOCK_STREAM; // TCP socket
int status = getaddrinfo(hostName, nullptr, &hints, &res);
if (status != 0) {
std::cerr << "getaddrinfo failed: " << gai_strerror(status) << std::endl;
return "";
}
struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>(res->ai_addr);
char ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &(addr->sin_addr), ip, sizeof(ip));
std::cout << "IP Address: " << ip << std::endl;
freeaddrinfo(res); // <20><>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD>ͷŵ<CDB7>ַ<EFBFBD><D6B7>Ϣ
return ip;
#endif
}
BOOL IOCPClient::ConnectServer(const char* szServerIP, unsigned short uPort)
@@ -129,12 +196,13 @@ BOOL IOCPClient::ConnectServer(const char* szServerIP, unsigned short uPort)
return FALSE;
}
#ifdef _WIN32
//<2F><><EFBFBD><EFBFBD>sockaddr_in<69>ṹ Ҳ<><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ض˵Ľṹ
sockaddr_in ServerAddr;
ServerAddr.sin_family = AF_INET; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> IP
ServerAddr.sin_port = htons(uPort);
// <20><>szServerIP<49><50><EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IPת<50><D7AA>
string server = ('0' <= szServerIP[0] && szServerIP[0] <= '9')
std::string server = ('0' <= szServerIP[0] && szServerIP[0] <= '9')
? szServerIP : GetIPAddress(szServerIP);
ServerAddr.sin_addr.S_un.S_addr = inet_addr(server.c_str());
@@ -147,12 +215,42 @@ BOOL IOCPClient::ConnectServer(const char* szServerIP, unsigned short uPort)
}
return FALSE;
}
#else
sockaddr_in ServerAddr = {};
ServerAddr.sin_family = AF_INET; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> IP
ServerAddr.sin_port = htons(uPort);
std::string server = ('0' <= szServerIP[0] && szServerIP[0] <= '9')
? szServerIP : GetIPAddress(szServerIP);
// <20><>szServerIP<49><50><EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IPת<50><D7AA>
// ʹ<><CAB9> inet_pton <20><><EFBFBD><EFBFBD> inet_addr (inet_pton <20><><EFBFBD><EFBFBD>֧<EFBFBD><D6A7> IPv4 <20><> IPv6)
if (inet_pton(AF_INET, server.c_str(), &ServerAddr.sin_addr) <= 0) {
std::cerr << "Invalid address or address not supported" << std::endl;
return false;
}
// <20><><EFBFBD><EFBFBD><EFBFBD>׽<EFBFBD><D7BD><EFBFBD>
m_sClientSocket = socket(AF_INET, SOCK_STREAM, 0);
if (m_sClientSocket == -1) {
std::cerr << "Failed to create socket" << std::endl;
return false;
}
// <20><><EFBFBD>ӵ<EFBFBD><D3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (connect(m_sClientSocket, (struct sockaddr*)&ServerAddr, sizeof(ServerAddr)) == -1) {
std::cerr << "Connection failed" << std::endl;
close(m_sClientSocket);
m_sClientSocket = -1; // <20><><EFBFBD><EFBFBD><EFBFBD>׽<EFBFBD><D7BD><EFBFBD><EFBFBD><EFBFBD>Ч
return false;
}
#endif
const int chOpt = 1; // True
// Set KeepAlive <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><>ֹ<EFBFBD><D6B9><EFBFBD><EFBFBD><EFBFBD>˲<EFBFBD><CBB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (setsockopt(m_sClientSocket, SOL_SOCKET, SO_KEEPALIVE,
(char *)&chOpt, sizeof(chOpt)) == 0)
{
#ifdef _WIN32
// <20><><EFBFBD>ó<EFBFBD>ʱ<EFBFBD><CAB1>ϸ<EFBFBD><CFB8>Ϣ
tcp_keepalive klive;
klive.onoff = 1; // <20><><EFBFBD>ñ<EFBFBD><C3B1><EFBFBD>
@@ -160,11 +258,20 @@ BOOL IOCPClient::ConnectServer(const char* szServerIP, unsigned short uPort)
klive.keepaliveinterval = 1000 * 5; // <20><><EFBFBD>Լ<EFBFBD><D4BC><EFBFBD>Ϊ5<CEAA><35> Resend if No-Reply
WSAIoctl(m_sClientSocket, SIO_KEEPALIVE_VALS,&klive,sizeof(tcp_keepalive),
NULL, 0,(unsigned long *)&chOpt,0,NULL);
#else
// <20><><EFBFBD>ñ<EFBFBD><C3B1><EFBFBD>ѡ<EFBFBD><D1A1>
SetKeepAliveOptions(m_sClientSocket);
#endif
}
if (m_hWorkThread == NULL){
#ifdef _WIN32
m_hWorkThread = (HANDLE)CreateThread(NULL, 0,
WorkThreadProc,(LPVOID)this, 0, NULL);
m_bWorkThread = m_hWorkThread ? S_RUN : S_STOP;
#else
pthread_t id = 0;
m_hWorkThread = (HANDLE)pthread_create(&id, nullptr, (void* (*)(void*))IOCPClient::WorkThreadProc, this);
#endif
}
Mprintf("<EFBFBD><EFBFBD><EFBFBD>ӷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˳ɹ<EFBFBD>.\n");
m_bConnected = TRUE;
@@ -176,7 +283,7 @@ DWORD WINAPI IOCPClient::WorkThreadProc(LPVOID lParam)
IOCPClient* This = (IOCPClient*)lParam;
char* szBuffer = new char[MAX_RECV_BUFFER];
fd_set fd;
const struct timeval tm = { 2, 0 };
struct timeval tm = { 2, 0 };
while (This->IsRunning()) // û<><C3BB><EFBFBD>˳<EFBFBD><CBB3><EFBFBD><EFBFBD><EFBFBD>һֱ<D2BB><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><D1AD><EFBFBD><EFBFBD>
{
@@ -187,7 +294,11 @@ DWORD WINAPI IOCPClient::WorkThreadProc(LPVOID lParam)
}
FD_ZERO(&fd);
FD_SET(This->m_sClientSocket, &fd);
#ifdef _WIN32
int iRet = select(NULL, &fd, NULL, NULL, &tm);
#else
int iRet = select(This->m_sClientSocket + 1, &fd, NULL, NULL, &tm);
#endif
if (iRet <= 0)
{
if (iRet == 0) Sleep(50);
@@ -206,21 +317,13 @@ DWORD WINAPI IOCPClient::WorkThreadProc(LPVOID lParam)
szBuffer, MAX_RECV_BUFFER, 0); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ض˷<D8B6><CBB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (iReceivedLength <= 0)
{
int a = GetLastError();
int a = WSAGetLastError();
This->Disconnect(); //<2F><><EFBFBD>մ<EFBFBD><D5B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if(This->m_exit_while_disconnect)
break;
}else{
//<2F><>ȷ<EFBFBD><C8B7><EFBFBD>վ͵<D5BE><CDB5><EFBFBD>OnRead<61><64><EFBFBD><EFBFBD><><D7AA>OnRead
This->OnServerReceiving(szBuffer, iReceivedLength);
if (This->m_Manager!=NULL && This->m_Manager->m_bIsDead)
{
Mprintf("****** Recv bye bye ******\n");
// <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7>˳<EFBFBD><CBB3>ͻ<EFBFBD><CDBB>˺<EFBFBD><CBBA><EFBFBD><EFBFBD>ضˣ<D8B6><CBA3><EFBFBD><EFBFBD>˳<EFBFBD><CBB3>ͻ<EFBFBD><CDBB><EFBFBD>
extern BOOL g_bExit;
g_bExit = This->m_Manager->m_bIsDead;
break;
}
}
}
}
@@ -285,8 +388,8 @@ VOID IOCPClient::OnServerReceiving(char* szBuffer, ULONG ulLength)
//<2F><>ѹ<EFBFBD>õ<EFBFBD><C3B5><EFBFBD><EFBFBD>ݺͳ<DDBA><CDB3>ȴ<EFBFBD><C8B4>ݸ<EFBFBD><DDB8><EFBFBD><EFBFBD><EFBFBD>Manager<65><72><EFBFBD>д<EFBFBD><D0B4><EFBFBD> ע<><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˶<EFBFBD>̬
//<2F><><EFBFBD><EFBFBD>m_pManager<65>е<EFBFBD><D0B5><EFBFBD><EFBFBD>һ<E0B2BB><D2BB><EFBFBD><EFBFBD><EFBFBD>ɵ<EFBFBD><C9B5>õ<EFBFBD>OnReceive<76><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>
if (m_Manager)
m_Manager->OnReceive((PBYTE)m_DeCompressedBuffer.GetBuffer(0),
if (m_DataProcess)
m_DataProcess(m_Manager, (PBYTE)m_DeCompressedBuffer.GetBuffer(0),
m_DeCompressedBuffer.GetBufferLength());
}
else{