fix: #71 Development of a simple Linux Client
This commit is contained in:
@@ -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{
|
||||
|
||||
Reference in New Issue
Block a user