//接收端
#pragma pack(1)
struct protocol_head_
{
int MainMsgID; // 主消息ID
int SubMsgID; // 子消息ID
int DataLen; // 数据长度,不包含头
int Reserve1; // 预留字段1
};
void Test::recvData()
{
LOG_DEBUGGING("启动接收数据线程");
int headLen = sizeof(protocol_head_);
char *pHeadData = new char[headLen];
char *pData = nullptr;
int npDataLen = 0;
while (m_bInited)
{
if (!m_bConnected)
{
Sleep(1);
continue;
}
int nRecvLen = 0;
memset(pHeadData, 0, headLen);
// 读取头数据,先收固定长度包头
while (1)
{
int len = ::recv(m_s, pHeadData + nRecvLen, headLen - nRecvLen, 0);
if (len <= 0)
{// 连接异常
m_bConnected = false;
break;
}
else
{
nRecvLen += len;
if (nRecvLen >= headLen)
{
break;
}
}
}
if (!m_bConnected) continue;
nRecvLen = 0;
protocol_head_ *pHead = (protocol_head_*)pHeadData;
// 读取消息体,(从包头取长度)
int bodyLen = pHead->DataLen;
if (bodyLen < 0)
{
m_bConnected = false;
continue;
}
if (bodyLen == 0)
{
continue;
}
else
{
if (pData == nullptr || headLen + bodyLen > npDataLen)
{
if (pData != nullptr) delete[]pData;
pData = new char[headLen + bodyLen];
npDataLen = headLen + bodyLen;
}
memcpy(pData, pHeadData, headLen);
//再按长度收包体
while (1)
{
int len = ::recv(m_s, pData + nRecvLen + headLen, bodyLen - nRecvLen, 0);
if (len <= 0)
{// 连接异常
m_bConnected = false;
break;
}
else
{
nRecvLen += len;
if (nRecvLen >= bodyLen)
{
break;
}
}
}
if (!m_bConnected) continue;
}
//一包一包处理
if (pHead->MainMsgID == N_NOTIFY && pHead->SubMsgID == N_DACTYLOGRAM__INFO)
{
}
}
void Test:recvData()
{
LOG_DEBUGGING("启动接收数据线程(buffer模型)");
const int HEAD_LEN = sizeof(protocol_head_);
const int MAX_PACKET_SIZE = 1024 * 1024; // 1MB(根据业务调)
const int MAX_BUFFER_SIZE = 2 * 1024 * 1024;
std::vector<char> buffer;
buffer.reserve(64 * 1024); // 预留64KB,减少扩容
char tmp[4096];
while (m_bInited)
{
if (!m_bConnected)
{
Sleep(1);
continue;
}
// ================== 1️⃣ 收数据 ==================
int len = recv(m_s, tmp, sizeof(tmp), 0);
if (len == 0)
{
LOG_DEBUGGING("socket closed by peer");
m_bConnected = false;
continue;
}
else if (len < 0)
{
int err = WSAGetLastError();
if (err == WSAEWOULDBLOCK)
{
Sleep(1);
continue;
}
LOG_DEBUGGING("recv error: %d", err);
m_bConnected = false;
continue;
}
// 写入 buffer
buffer.insert(buffer.end(), tmp, tmp + len);
// 防止buffer无限增长
if (buffer.size() > MAX_BUFFER_SIZE)
{
LOG_DEBUGGING("buffer overflow, reset connection");
m_bConnected = false;
buffer.clear();
continue;
}
// ================== 2️⃣ 解析数据 ==================
size_t offset = 0;
while (true)
{
// 2.1 不够一个包头
if (buffer.size() - offset < HEAD_LEN)
break;
// 2.2 读取头(不能直接指针长期用)
protocol_head_ head;
memcpy(&head, buffer.data() + offset, HEAD_LEN);
// ⚠️ 如果跨平台,打开这行
// head.DataLen = ntohl(head.DataLen);
int bodyLen = head.DataLen;
// 2.3 长度校验(非常关键)
if (bodyLen <= 0 || bodyLen > MAX_PACKET_SIZE)
{
LOG_DEBUGGING("invalid bodyLen=%d, disconnect", bodyLen);
m_bConnected = false;
break;
}
int totalLen = HEAD_LEN + bodyLen;
// 2.4 不够完整包
if (buffer.size() - offset < totalLen)
break;
// ================== 3️⃣ 处理完整包 ==================
char* packet = buffer.data() + offset;
protocol_head_* pHead = (protocol_head_*)packet;
// 👉 业务分发
if (pHead->MainMsgID == N_NOTIFY && pHead->SubMsgID == N_DACTYLOGRAM__INFO)
{
}
// 处理完一个包 → 偏移
offset += totalLen;
}
// ================== 4️⃣ 清理已处理数据 ==================
if (offset > 0)
{
buffer.erase(buffer.begin(), buffer.begin() + offset);
}
}
#endif
}