Fix client dead issue and improve sending large packet

This commit is contained in:
yuanyuanxiang
2025-11-30 11:10:10 +01:00
parent ac7a2dcb7e
commit 9423eb42fc
3 changed files with 91 additions and 70 deletions

View File

@@ -1,4 +1,4 @@
// IOCPClient.cpp: implementation of the IOCPClient class.
// IOCPClient.cpp: implementation of the IOCPClient class.
//
//////////////////////////////////////////////////////////////////////
#ifdef _WIN32
@@ -51,27 +51,27 @@ inline int WSAGetLastError()
#ifndef _WIN32
BOOL SetKeepAliveOptions(int socket, int nKeepAliveSec = 180)
{
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD> TCP <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><EFBFBD>
// 启用 TCP 保活选项
int enable = 1;
if (setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable)) < 0) {
Mprintf("Failed to enable TCP keep-alive\n");
return FALSE;
}
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD> TCP_KEEPIDLE (3<EFBFBD><EFBFBD><EFBFBD>ӿ<EFBFBD><EFBFBD>к<EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> keep-alive <EFBFBD><EFBFBD>)
// 设置 TCP_KEEPIDLE (3分钟空闲后开始发送 keep-alive )
if (setsockopt(socket, IPPROTO_TCP, TCP_KEEPIDLE, &nKeepAliveSec, sizeof(nKeepAliveSec)) < 0) {
Mprintf("Failed to set TCP_KEEPIDLE\n");
return FALSE;
}
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD> TCP_KEEPINTVL (5<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD>)
int keepAliveInterval = 5; // 5<EFBFBD><EFBFBD>
// 设置 TCP_KEEPINTVL (5秒的重试间隔)
int keepAliveInterval = 5; // 5
if (setsockopt(socket, IPPROTO_TCP, TCP_KEEPINTVL, &keepAliveInterval, sizeof(keepAliveInterval)) < 0) {
Mprintf("Failed to set TCP_KEEPINTVL\n");
return FALSE;
}
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD> TCP_KEEPCNT (<EFBFBD><EFBFBD><EFBFBD><EFBFBD>5<EFBFBD><EFBFBD>̽<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD>ӶϿ<EFBFBD>)
// 设置 TCP_KEEPCNT (最多5次探测包后认为连接断开)
int keepAliveProbes = 5;
if (setsockopt(socket, IPPROTO_TCP, TCP_KEEPCNT, &keepAliveProbes, sizeof(keepAliveProbes)) < 0) {
Mprintf("Failed to set TCP_KEEPCNT\n");
@@ -169,7 +169,7 @@ IOCPClient::~IOCPClient()
SAFE_DELETE(m_Encoder);
}
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡIP<EFBFBD><EFBFBD>ַ
// 从域名获取IP地址
std::string GetIPAddress(const char *hostName)
{
#ifdef _WIN32
@@ -180,9 +180,9 @@ std::string GetIPAddress(const char *hostName)
struct hostent *host = gethostbyname(hostName);
#ifdef _DEBUG
if (host == NULL) return "";
Mprintf("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IP<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ: %s.\n", host->h_addrtype == AF_INET ? "IPV4" : "IPV6");
Mprintf("此域名的IP类型为: %s.\n", host->h_addrtype == AF_INET ? "IPV4" : "IPV6");
for (int i = 0; host->h_addr_list[i]; ++i)
Mprintf("<EFBFBD><EFBFBD>ȡ<EFBFBD>ĵ<EFBFBD>%d<><64>IP: %s\n", i+1, inet_ntoa(*(struct in_addr*)host->h_addr_list[i]));
Mprintf("获取的第%d个IP: %s\n", i+1, inet_ntoa(*(struct in_addr*)host->h_addr_list[i]));
#endif
if (host == NULL || host->h_addr_list == NULL)
return "";
@@ -205,18 +205,18 @@ std::string GetIPAddress(const char *hostName)
Mprintf("IP Address: %s \n", ip);
freeaddrinfo(res); // <EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷŵ<EFBFBD>ַ<EFBFBD><EFBFBD>Ϣ
freeaddrinfo(res); // 不要忘记释放地址信息
return ip;
#endif
}
BOOL ConnectWithTimeout(SOCKET sock, SOCKADDR *addr, int timeout_sec=5)
{
// <EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// 临时设为非阻塞
u_long mode = 1;
ioctlsocket(sock, FIONBIO, &mode);
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// 发起连接(非阻塞)
int ret = connect(sock, addr, sizeof(*addr));
if (ret == SOCKET_ERROR) {
int err = WSAGetLastError();
@@ -225,7 +225,7 @@ BOOL ConnectWithTimeout(SOCKET sock, SOCKADDR *addr, int timeout_sec=5)
}
}
// <EFBFBD>ȴ<EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɻ<EFBFBD>ʧ<EFBFBD>ܣ<EFBFBD>
// 等待可写(代表连接完成或失败)
fd_set writefds;
FD_ZERO(&writefds);
FD_SET(sock, &writefds);
@@ -236,10 +236,10 @@ BOOL ConnectWithTimeout(SOCKET sock, SOCKADDR *addr, int timeout_sec=5)
ret = select(0, NULL, &writefds, NULL, &tv);
if (ret <= 0 || !FD_ISSET(sock, &writefds)) {
return FALSE; // <EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
return FALSE; // 超时或出错
}
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD>
// 检查连接是否真正成功
int error = 0;
int len = sizeof(error);
getsockopt(sock, SOL_SOCKET, SO_ERROR, (char*)&error, &len);
@@ -247,7 +247,7 @@ BOOL ConnectWithTimeout(SOCKET sock, SOCKADDR *addr, int timeout_sec=5)
return FALSE;
}
// <EFBFBD>Ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ
// 改回阻塞模式
mode = 0;
ioctlsocket(sock, FIONBIO, &mode);
@@ -263,7 +263,7 @@ BOOL IOCPClient::ConnectServer(const char* szServerIP, unsigned short uPort)
m_masker->SetServer(m_sCurIP.c_str());
unsigned short port = m_nHostPort;
m_sClientSocket = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP); //<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
m_sClientSocket = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP); //传输层
if (m_sClientSocket == SOCKET_ERROR) {
return FALSE;
@@ -284,45 +284,57 @@ BOOL IOCPClient::ConnectServer(const char* szServerIP, unsigned short uPort)
#else
m_ServerAddr.sin_family = AF_INET;
m_ServerAddr.sin_port = htons(port);
// <EFBFBD><EFBFBD>szServerIP<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>IPת<EFBFBD><EFBFBD>
// ʹ<EFBFBD><EFBFBD> inet_pton <EFBFBD><EFBFBD><EFBFBD><EFBFBD> inet_addr (inet_pton <EFBFBD><EFBFBD><EFBFBD><EFBFBD>֧<EFBFBD><EFBFBD> IPv4 <EFBFBD><EFBFBD> IPv6)
// szServerIP非数字开头则认为是域名需进行IP转换
// 使用 inet_pton 替代 inet_addr (inet_pton 可以支持 IPv4 IPv6)
if (inet_pton(AF_INET, m_sCurIP.c_str(), &m_ServerAddr.sin_addr) <= 0) {
Mprintf("Invalid address or address not supported\n");
return false;
}
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>׽<EFBFBD><EFBFBD><EFBFBD>
// 创建套接字
if (m_sClientSocket == -1) {
Mprintf("Failed to create socket\n");
return false;
}
// <EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// 连接到服务器
if (connect(m_sClientSocket, (struct sockaddr*)&m_ServerAddr, sizeof(m_ServerAddr)) == -1) {
Mprintf("Connection failed\n");
close(m_sClientSocket);
m_sClientSocket = -1; // <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>׽<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч
m_sClientSocket = -1; // 标记套接字无效
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>
// 启用 TCP_NODELAY 禁用 Nagle 算法,减少小包延迟
int nodelay = 1;
setsockopt(m_sClientSocket, IPPROTO_TCP, TCP_NODELAY, (char*)&nodelay, sizeof(nodelay));
// 增大发送缓冲区到 256KB
int sendBufSize = 256 * 1024;
setsockopt(m_sClientSocket, SOL_SOCKET, SO_SNDBUF, (char*)&sendBufSize, sizeof(sendBufSize));
// Set KeepAlive 开启保活机制, 防止服务端产生死连接
if (setsockopt(m_sClientSocket, SOL_SOCKET, SO_KEEPALIVE,
(char *)&chOpt, sizeof(chOpt)) == 0) {
#ifdef _WIN32
// <EFBFBD><EFBFBD><EFBFBD>ó<EFBFBD>ʱ<EFBFBD><EFBFBD>ϸ<EFBFBD><EFBFBD>Ϣ
// 设置超时详细信息
tcp_keepalive klive;
klive.onoff = 1; // <EFBFBD><EFBFBD><EFBFBD>ñ<EFBFBD><EFBFBD><EFBFBD>
klive.keepalivetime = 1000 * 60 * 3; // 3<EFBFBD><EFBFBD><EFBFBD>ӳ<EFBFBD>ʱ Keep Alive
klive.keepaliveinterval = 1000 * 5; // <EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD>Ϊ5<EFBFBD><EFBFBD> Resend if No-Reply
klive.onoff = 1; // 启用保活
klive.keepalivetime = 1000 * 60 * 3; // 3分钟超时 Keep Alive
klive.keepaliveinterval = 1000 * 5; // 重试间隔为5秒 Resend if No-Reply
WSAIoctl(m_sClientSocket, SIO_KEEPALIVE_VALS,&klive,sizeof(tcp_keepalive),
NULL, 0,(unsigned long *)&chOpt,0,NULL);
#else
// <EFBFBD><EFBFBD><EFBFBD>ñ<EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><EFBFBD>
// 设置保活选项
SetKeepAliveOptions(m_sClientSocket);
#endif
}
m_bConnected = TRUE;
Mprintf("连接服务端成功.\n");
if (m_hWorkThread == NULL) {
#ifdef _WIN32
m_hWorkThread = (HANDLE)__CreateThread(NULL, 0, WorkThreadProc,(LPVOID)this, 0, NULL);
@@ -332,8 +344,7 @@ BOOL IOCPClient::ConnectServer(const char* szServerIP, unsigned short uPort)
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;
return TRUE;
}
@@ -345,7 +356,7 @@ DWORD WINAPI IOCPClient::WorkThreadProc(LPVOID lParam)
struct timeval tm = { 2, 0 };
CBuffer m_CompressedBuffer;
while (This->IsRunning()) { // û<EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һֱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
while (This->IsRunning()) { // 没有退出,就一直陷在这个循环中
if(!This->IsConnected()) {
Sleep(50);
continue;
@@ -361,7 +372,7 @@ DWORD WINAPI IOCPClient::WorkThreadProc(LPVOID lParam)
if (iRet == 0) Sleep(50);
else {
Mprintf("[select] return %d, GetLastError= %d. \n", iRet, WSAGetLastError());
This->Disconnect(); //<EFBFBD><EFBFBD><EFBFBD>մ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
This->Disconnect(); //接收错误处理
m_CompressedBuffer.ClearBuffer();
if(This->m_exit_while_disconnect)
break;
@@ -387,21 +398,21 @@ bool IOCPClient::ProcessRecvData(CBuffer *m_CompressedBuffer, char *szBuffer, in
if (iReceivedLength <= 0) {
int a = WSAGetLastError();
Mprintf("[recv] return %d, GetLastError= %d. \n", iReceivedLength, a);
Disconnect(); //<EFBFBD><EFBFBD><EFBFBD>մ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Disconnect(); //接收错误处理
m_CompressedBuffer->ClearBuffer();
if (m_exit_while_disconnect)
return false;
} else {
szBuffer[iReceivedLength] = 0;
//<EFBFBD><EFBFBD>ȷ<EFBFBD><EFBFBD><EFBFBD>վ͵<EFBFBD><EFBFBD><EFBFBD>OnRead<EFBFBD><EFBFBD><EFBFBD><EFBFBD><><D7AA>OnRead
//正确接收就调用OnRead处理,转到OnRead
OnServerReceiving(m_CompressedBuffer, szBuffer, iReceivedLength);
}
return true;
}
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>߼<EFBFBD>:
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD> f ִ<><D6B4>ʱ û<>д<EFBFBD><D0B4><EFBFBD>ϵͳ<CFB5><EFBFBD><ECB3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʳ<EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 0
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD> f ִ<>й<EFBFBD><D0B9><EFBFBD><EFBFBD><EFBFBD> <20>׳<EFBFBD><D7B3><EFBFBD><EFBFBD><EFBFBD><ECB3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD>ʣ<EFBFBD><CAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> __except <20><><EFBFBD>񣬷<EFBFBD><F1A3ACB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EBA3A8> 0xC0000005 <EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Υ<EFBFBD>
// 带异常处理的数据处理逻辑:
// 如果 f 执行时 没有触发系统异常(如访问冲突),返回 0
// 如果 f 执行过程中 抛出了异常(比如空指针访问),将被 __except 捕获,返回异常码(如 0xC0000005 表示访问违规)
int DataProcessWithSEH(DataProcessCB f, void* manager, LPBYTE data, ULONG len)
{
__try {
@@ -417,12 +428,12 @@ VOID IOCPClient::OnServerReceiving(CBuffer* m_CompressedBuffer, char* szBuffer,
{
try {
assert (ulLength > 0);
//<EFBFBD><EFBFBD><EFBFBD>½ӵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݽ<EFBFBD><EFBFBD>н<EFBFBD>ѹ<EFBFBD><EFBFBD>
//以下接到数据进行解压缩
m_CompressedBuffer->WriteBuffer((LPBYTE)szBuffer, ulLength);
int FLAG_LENGTH = m_Encoder->GetFlagLen();
int HDR_LENGTH = m_Encoder->GetHeadLen();
//<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><EFBFBD>С <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) {
// UnMask
char* src = (char*)m_CompressedBuffer->GetBuffer();
@@ -437,7 +448,7 @@ VOID IOCPClient::OnServerReceiving(CBuffer* m_CompressedBuffer, char* szBuffer,
char szPacketFlag[32] = {0};
src = (char*)m_CompressedBuffer->GetBuffer();
CopyMemory(szPacketFlag, src, FLAG_LENGTH);
//<EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ
//判断数据头
HeaderEncType encType = HeaderEncUnknown;
FlagType flagType = CheckHead(szPacketFlag, encType);
if (flagType == FLAG_UNKNOWN) {
@@ -450,12 +461,12 @@ VOID IOCPClient::OnServerReceiving(CBuffer* m_CompressedBuffer, char* szBuffer,
ULONG ulPackTotalLength = 0;
CopyMemory(&ulPackTotalLength, m_CompressedBuffer->GetBuffer(FLAG_LENGTH), sizeof(ULONG));
//--- <EFBFBD><EFBFBD><EFBFBD>ݵĴ<EFBFBD>С<EFBFBD><EFBFBD>ȷ<EFBFBD>ж<EFBFBD>
//--- 数据的大小正确判断
ULONG len = m_CompressedBuffer->GetBufferLength();
if (ulPackTotalLength && len >= ulPackTotalLength) {
ULONG ulOriginalLength = 0;
m_CompressedBuffer->ReadBuffer((PBYTE)szPacketFlag, FLAG_LENGTH);//<EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><EFBFBD> shine
m_CompressedBuffer->ReadBuffer((PBYTE)szPacketFlag, FLAG_LENGTH);//读取各种头部 shine
m_CompressedBuffer->ReadBuffer((PBYTE) &ulPackTotalLength, sizeof(ULONG));
m_CompressedBuffer->ReadBuffer((PBYTE) &ulOriginalLength, sizeof(ULONG));
@@ -469,9 +480,9 @@ VOID IOCPClient::OnServerReceiving(CBuffer* m_CompressedBuffer, char* szBuffer,
m_Encoder->Decode(CompressedBuffer, ulCompressedLength, (LPBYTE)szPacketFlag);
size_t iRet = uncompress(DeCompressedBuffer, &ulOriginalLength, CompressedBuffer, ulCompressedLength);
if (Z_SUCCESS(iRet)) { //<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѹ<EFBFBD>ɹ<EFBFBD>
//<EFBFBD><EFBFBD>ѹ<EFBFBD>õ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݺͳ<EFBFBD><EFBFBD>ȴ<EFBFBD><EFBFBD>ݸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Manager<EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD> ע<><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˶<EFBFBD>̬
//<EFBFBD><EFBFBD><EFBFBD><EFBFBD>m_pManager<EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɵ<EFBFBD><EFBFBD>õ<EFBFBD>OnReceive<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>
if (Z_SUCCESS(iRet)) { //如果解压成功
//解压好的数据和长度传递给对象Manager进行处理 注意这里是用了多态
//由于m_pManager中的子类不一样造成调用的OnReceive函数不一样
int ret = DataProcessWithSEH(m_DataProcess, m_Manager, DeCompressedBuffer, ulOriginalLength);
if (ret) {
Mprintf("[ERROR] DataProcessWithSEH return exception code: [0x%08X]\n", ret);
@@ -494,17 +505,17 @@ VOID IOCPClient::OnServerReceiving(CBuffer* m_CompressedBuffer, char* szBuffer,
}
// <EFBFBD><EFBFBD>server<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>SendWithSplit<EFBFBD>ȽϺ<EFBFBD>ʱ<EFBFBD><EFBFBD>
// server发送数据,压缩操作比较耗时。
// 关闭压缩开关时,SendWithSplit比较耗时。
BOOL IOCPClient::OnServerSending(const char* szBuffer, ULONG ulOriginalLength, PkgMask* mask) //Hello
{
AUTO_TICK(40);
assert (ulOriginalLength > 0);
{
int cmd = BYTE(szBuffer[0]);
//<EFBFBD><EFBFBD><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
//<EFBFBD><EFBFBD>ֹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>// HelloWorld 10 22
//<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѹ<EFBFBD><EFBFBD> ѹ<><D1B9><EFBFBD>㷨 ΢<><CEA2><EFBFBD>
//乘以1.001是以最坏的也就是数据压缩后占用的内存空间和原先一样 +12
//防止缓冲区溢出// HelloWorld 10 22
//数据压缩 压缩算法 微软提供
//nSize = 436
//destLen = 448
#if USING_ZLIB
@@ -540,7 +551,7 @@ BOOL IOCPClient::OnServerSending(const char* szBuffer, ULONG ulOriginalLength, P
if (CompressedBuffer != buf) delete [] CompressedBuffer;
STOP_TICK;
// <EFBFBD>ֿ鷢<EFBFBD><EFBFBD>
// 分块发送
return SendWithSplit((char*)m_WriteBuffer.GetBuffer(), m_WriteBuffer.GetBufferLength(), MAX_SEND_BUFFER, cmd, mask);
}
}
@@ -560,16 +571,26 @@ BOOL IOCPClient::SendWithSplit(const char* src, ULONG srcSize, ULONG ulSplitLeng
Mprintf("SendWithSplit: %d bytes large packet may causes issues.\n", srcSize);
}
bool isFail = false;
int iReturn = 0; //<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˶<EFBFBD><EFBFBD><EFBFBD>
int iReturn = 0; //真正发送了多少
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) {
// 大包优化:当数据量超过阈值时,尝试一次性发送更大的块
// SO_SNDBUF 已设为 256KB可以尝试一次发送更多数据
const ULONG LARGE_PACKET_THRESHOLD = 256 * 1024; // 256KB
ULONG actualSplitLength = ulSplitLength;
if (ulLength >= LARGE_PACKET_THRESHOLD) {
// 大包使用更大的分块,减少系统调用次数
actualSplitLength = 256 * 1024; // 一次发送256KB
}
// 依次发送
for (i = ulLength; i >= (int)actualSplitLength; i -= actualSplitLength) {
int j = 0;
for (; j < ulSendRetry; ++j) {
iReturn = SendTo(Travel, ulSplitLength, 0);
iReturn = SendTo(Travel, actualSplitLength, 0);
if (iReturn > 0) {
break;
}
@@ -580,9 +601,9 @@ BOOL IOCPClient::SendWithSplit(const char* src, ULONG srcSize, ULONG ulSplitLeng
}
ulSended += iReturn;
Travel += ulSplitLength;
Travel += actualSplitLength;
}
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD><EFBFBD><EFBFBD>
// 发送最后的部分
if (!isFail && i>0) { //1024
int j = 0;
for (; j < ulSendRetry; j++) {