Files
SimpleRemoter/client/IOCPClient.cpp
2019-05-08 11:47:55 +08:00

409 lines
10 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// IOCPClient.cpp: implementation of the IOCPClient class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "IOCPClient.h"
#include <IOSTREAM>
#if USING_ZLIB
#include "zlib.h"
#define Z_FAILED(p) (Z_OK != (p))
#define Z_SUCCESS(p) (!Z_FAILED(p))
#else
#if USING_LZ4
#include "lz4/lz4.h"
#pragma comment(lib, "lz4/lz4.lib")
#define Z_FAILED(p) (0 == (p))
#define Z_SUCCESS(p) (!Z_FAILED(p))
#define compress(dest, destLen, source, sourceLen) LZ4_compress_default((const char*)source, (char*)dest, sourceLen, *(destLen))
#define uncompress(dest, destLen, source, sourceLen) LZ4_decompress_safe((const char*)source, (char*)dest, sourceLen, *(destLen))
#else
#include "zstd/zstd.h"
#pragma comment(lib, "zstd/zstd.lib")
#define Z_FAILED(p) ZSTD_isError(p)
#define Z_SUCCESS(p) (!Z_FAILED(p))
#define compress(dest, destLen, source, sourceLen) ZSTD_compress(dest, *(destLen), source, sourceLen, ZSTD_CLEVEL_DEFAULT)
#define uncompress(dest, destLen, source, sourceLen) ZSTD_decompress(dest, *(destLen), source, sourceLen)
#endif
#endif
#include <assert.h>
#include "Manager.h"
using namespace std;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
VOID IOCPClient::setManagerCallBack(CManager* Manager)
{
m_Manager = Manager;
}
IOCPClient::IOCPClient(bool exit_while_disconnect)
{
m_Manager = NULL;
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
m_sClientSocket = INVALID_SOCKET;
m_hWorkThread = NULL;
m_bWorkThread = S_STOP;
memset(m_szPacketFlag, 0, sizeof(m_szPacketFlag));
memcpy(m_szPacketFlag,"Shine",FLAG_LENGTH);
m_bIsRunning = TRUE;
m_bConnected = FALSE;
InitializeCriticalSection(&m_cs);
m_exit_while_disconnect = exit_while_disconnect;
}
IOCPClient::~IOCPClient()
{
m_bIsRunning = FALSE;
if (m_sClientSocket!=INVALID_SOCKET)
{
closesocket(m_sClientSocket);
m_sClientSocket = INVALID_SOCKET;
}
if (m_hWorkThread!=NULL)
{
CloseHandle(m_hWorkThread);
m_hWorkThread = NULL;
}
WSACleanup();
while (S_RUN == m_bWorkThread)
Sleep(10);
DeleteCriticalSection(&m_cs);
m_bWorkThread = S_END;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡIP<49><50>ַ
inline string GetIPAddress(const char *hostName)
{
struct hostent *host = gethostbyname(hostName);
#ifdef _DEBUG
printf("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IP<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ: %s.\n", host->h_addrtype == AF_INET ? "IPV4" : "IPV6");
for (int i = 0; host->h_addr_list[i]; ++i)
printf("<EFBFBD><EFBFBD>ȡ<EFBFBD>ĵ<EFBFBD>%d<><64>IP: %s\n", i+1, inet_ntoa(*(struct in_addr*)host->h_addr_list[i]));
#endif
return host ? inet_ntoa(*(struct in_addr*)host->h_addr_list[0]) : "";
}
BOOL IOCPClient::ConnectServer(char* szServerIP, unsigned short uPort)
{
m_sClientSocket = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (m_sClientSocket == SOCKET_ERROR)
{
return FALSE;
}
//<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')
? szServerIP : GetIPAddress(szServerIP);
ServerAddr.sin_addr.S_un.S_addr = inet_addr(server.c_str());
if (connect(m_sClientSocket,(SOCKADDR *)&ServerAddr,sizeof(sockaddr_in)) == SOCKET_ERROR)
{
if (m_sClientSocket!=INVALID_SOCKET)
{
closesocket(m_sClientSocket);
m_sClientSocket = INVALID_SOCKET;
}
return FALSE;
}
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)
{
// <20><><EFBFBD>ó<EFBFBD>ʱ<EFBFBD><CAB1>ϸ<EFBFBD><CFB8>Ϣ
tcp_keepalive klive;
klive.onoff = 1; // <20><><EFBFBD>ñ<EFBFBD><C3B1><EFBFBD>
klive.keepalivetime = 1000 * 60 * 3; // 3<><33><EFBFBD>ӳ<EFBFBD>ʱ Keep Alive
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);
}
if (m_hWorkThread == NULL){
m_hWorkThread = (HANDLE)CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)WorkThreadProc,(LPVOID)this, 0, NULL);
m_bWorkThread = m_hWorkThread ? S_RUN : S_STOP;
}
std::cout<<"<EFBFBD><EFBFBD><EFBFBD>ӷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˳ɹ<EFBFBD>.\n";
m_bConnected = TRUE;
return TRUE;
}
DWORD WINAPI IOCPClient::WorkThreadProc(LPVOID lParam)
{
IOCPClient* This = (IOCPClient*)lParam;
char szBuffer[MAX_RECV_BUFFER] = {0};
fd_set fd;
const 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>
{
if(!This->IsConnected())
{
Sleep(50);
continue;
}
FD_ZERO(&fd);
FD_SET(This->m_sClientSocket, &fd);
int iRet = select(NULL, &fd, NULL, NULL, &tm);
if (iRet <= 0)
{
if (iRet == 0) Sleep(50);
else
{
printf("[select] return %d, GetLastError= %d. \n", iRet, WSAGetLastError());
This->Disconnect(); //<2F><><EFBFBD>մ<EFBFBD><D5B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if(This->m_exit_while_disconnect)
break;
}
}
else if (iRet > 0)
{
memset(szBuffer, 0, sizeof(szBuffer));
int iReceivedLength = recv(This->m_sClientSocket,
szBuffer,sizeof(szBuffer), 0); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ض˷<D8B6><CBB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (iReceivedLength <= 0)
{
int a = GetLastError();
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->m_bIsDead)
{
printf("****** 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;
}
}
}
}
This->m_bWorkThread = S_STOP;
This->m_bIsRunning = FALSE;
return 0xDEAD;
}
VOID IOCPClient::OnServerReceiving(char* szBuffer, ULONG ulLength)
{
try
{
assert (ulLength > 0);
//<2F><><EFBFBD>½ӵ<C2BD><D3B5><EFBFBD><EFBFBD>ݽ<EFBFBD><DDBD>н<EFBFBD>ѹ<EFBFBD><D1B9>
CBuffer m_CompressedBuffer;
m_CompressedBuffer.WriteBuffer((LPBYTE)szBuffer, ulLength);
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7>С <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǾͲ<C7BE><CDB2><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
while (m_CompressedBuffer.GetBufferLength() > HDR_LENGTH)
{
char szPacketFlag[FLAG_LENGTH + 3] = {0};
CopyMemory(szPacketFlag, m_CompressedBuffer.GetBuffer(),FLAG_LENGTH);
//<2F>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD>ͷ
if (memcmp(m_szPacketFlag, szPacketFlag, FLAG_LENGTH) != 0)
{
throw "Bad Buffer";
}
ULONG ulPackTotalLength = 0;
CopyMemory(&ulPackTotalLength, m_CompressedBuffer.GetBuffer(FLAG_LENGTH),
sizeof(ULONG));
//--- <20><><EFBFBD>ݵĴ<DDB5>С<EFBFBD><D0A1>ȷ<EFBFBD>ж<EFBFBD>
if (ulPackTotalLength &&
(m_CompressedBuffer.GetBufferLength()) >= ulPackTotalLength)
{
m_CompressedBuffer.ReadBuffer((PBYTE)szPacketFlag, FLAG_LENGTH);//<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7> shine
m_CompressedBuffer.ReadBuffer((PBYTE) &ulPackTotalLength, sizeof(ULONG));
ULONG ulOriginalLength = 0;
m_CompressedBuffer.ReadBuffer((PBYTE) &ulOriginalLength, sizeof(ULONG));
//50
ULONG ulCompressedLength = ulPackTotalLength - HDR_LENGTH;
PBYTE CompressedBuffer = new BYTE[ulCompressedLength];
PBYTE DeCompressedBuffer = new BYTE[ulOriginalLength];
m_CompressedBuffer.ReadBuffer(CompressedBuffer, ulCompressedLength);
int iRet = uncompress(DeCompressedBuffer,
&ulOriginalLength, CompressedBuffer, ulCompressedLength);
if (Z_SUCCESS(iRet))//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѹ<EFBFBD>ɹ<EFBFBD>
{
CBuffer m_DeCompressedBuffer;
m_DeCompressedBuffer.WriteBuffer(DeCompressedBuffer,
ulOriginalLength);
//<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>
m_Manager->OnReceive((PBYTE)m_DeCompressedBuffer.GetBuffer(0),
m_DeCompressedBuffer.GetBufferLength());
}
else{
printf("[ERROR] uncompress failed \n");
delete [] CompressedBuffer;
delete [] DeCompressedBuffer;
throw "Bad Buffer";
}
delete [] CompressedBuffer;
delete [] DeCompressedBuffer;
}
else
break;
}
}catch(...) { }
}
BOOL IOCPClient::OnServerSending(const char* szBuffer, ULONG ulOriginalLength) //Hello
{
AUTO_TICK(10);
assert (ulOriginalLength > 0);
{
//<2F><><EFBFBD><EFBFBD>1.001<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD>õ<EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD> +12
//<2F><>ֹ<EFBFBD><D6B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>// HelloWorld 10 22
//<2F><><EFBFBD><EFBFBD>ѹ<EFBFBD><D1B9> ѹ<><D1B9><EFBFBD>㷨 ΢<><CEA2><EFBFBD>
//nSize = 436
//destLen = 448
#if USING_ZLIB
unsigned long ulCompressedLength = (double)ulOriginalLength * 1.001 + 12;
#elif USING_LZ4
unsigned long ulCompressedLength = LZ4_compressBound(ulOriginalLength);
#else
unsigned long ulCompressedLength = ZSTD_compressBound(ulOriginalLength);
#endif
LPBYTE CompressedBuffer = new BYTE[ulCompressedLength];
int iRet = compress(CompressedBuffer, &ulCompressedLength, (PBYTE)szBuffer, ulOriginalLength);
if (Z_FAILED(iRet))
{
printf("[ERROR] compress failed \n");
delete [] CompressedBuffer;
return FALSE;
}
#if !USING_ZLIB
ulCompressedLength = iRet;
#endif
ULONG ulPackTotalLength = ulCompressedLength + HDR_LENGTH;
CBuffer m_WriteBuffer;
m_WriteBuffer.WriteBuffer((PBYTE)m_szPacketFlag, FLAG_LENGTH);
m_WriteBuffer.WriteBuffer((PBYTE) &ulPackTotalLength,sizeof(ULONG));
// 5 4
//[Shine][ 30 ]
m_WriteBuffer.WriteBuffer((PBYTE)&ulOriginalLength, sizeof(ULONG));
// 5 4 4
//[Shine][ 30 ][5]
m_WriteBuffer.WriteBuffer(CompressedBuffer,ulCompressedLength);
delete [] CompressedBuffer;
CompressedBuffer = NULL;
// <20>ֿ鷢<D6BF><E9B7A2>
//shine[0035][0010][HelloWorld+12]
return SendWithSplit((char*)m_WriteBuffer.GetBuffer(), m_WriteBuffer.GetBufferLength(),
MAX_SEND_BUFFER);
}
}
// 5 2 // 2 2 1
BOOL IOCPClient::SendWithSplit(const char* szBuffer, ULONG ulLength, ULONG ulSplitLength)
{
int iReturn = 0; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˶<EFBFBD><CBB6><EFBFBD>
const char* Travel = szBuffer;
int i = 0;
int ulSended = 0;
const int ulSendRetry = 15;
// <20><><EFBFBD>η<EFBFBD><CEB7><EFBFBD>
for (i = ulLength; i >= ulSplitLength; i -= ulSplitLength)
{
int j = 0;
for (; j < ulSendRetry; ++j)
{
iReturn = send(m_sClientSocket, Travel, ulSplitLength, 0);
if (iReturn > 0)
{
break;
}
}
if (j == ulSendRetry)
{
return FALSE;
}
ulSended += iReturn;
Travel += ulSplitLength;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD><C4B2><EFBFBD>
if (i>0) //1024
{
int j = 0;
for (; j < ulSendRetry; j++)
{
iReturn = send(m_sClientSocket, (char*)Travel,i,0);
if (iReturn > 0)
{
break;
}
}
if (j == ulSendRetry)
{
return FALSE;
}
ulSended += iReturn;
}
return (ulSended == ulLength) ? TRUE : FALSE;
}
VOID IOCPClient::Disconnect()
{
std::cout<<"<EFBFBD>Ͽ<EFBFBD><EFBFBD>ͷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.\n";
CancelIo((HANDLE)m_sClientSocket);
closesocket(m_sClientSocket);
m_sClientSocket = INVALID_SOCKET;
m_bConnected = FALSE;
}
VOID IOCPClient::RunEventLoop(const BOOL &bCondition)
{
OutputDebugStringA("======> RunEventLoop begin\n");
while (m_bIsRunning && bCondition)
Sleep(200);
OutputDebugStringA("======> RunEventLoop end\n");
}