18,363
社区成员




给每一步定义一个网络标识:
enum FILETRANSFLAG
{
FTS_SIZE = 1,
FTS_DATA,
FTS_OK
};
数据包的设计
每一步都是分为包头和包体:
struct CPacketHeader
{
FILETRANSFLAG m_nFlag; //标志
int m_nDataLen; //数据包长度
};
以下代码为伪码, 没有考虑出错, 安全等细节,如下:
//发送端;
if (pData != NULL && lDataSize > 0)
{
if (m_connectSocket == INVALID_SOCKET)
{
return;
}
int nRet = 0;
DWORD nSendCount = 0;
DWORD nSendTotalCount = 0;
CPacketHeader header;
//发送数据长度;
header.m_nFlag = FTS_SIZE;
header.m_nDataLen = lDataSize;
nRet = send(m_connectSocket, (LPCSTR)&header, sizeof(CPacketHeader), 0);
while(nSendTotalCount < lDataSize)
{
//发送包头;
header.m_nFlag = FTS_DATA;
header.m_nDataLen = 1024;
nRet = send(m_connectSocket, (LPCSTR)&header, sizeof(CPacketHeader), 0);
//发送数据;
nSendCount = send(m_connectSocket,(char *)pData, 1024, 0);
if (nSendCount == SOCKET_ERROR)
{
break;
}
else
{
nSendTotalCount += nSendCount;
}
}
//发送结束;
header.m_nFlag = FTS_OK;
header.m_nDataLen = 0;
nRet = send(m_connectSocket, (LPCSTR)&header, sizeof(CPacketHeader), 0);
}
//接收端;
long lDataLen = 0;
int nRecvLen = 0;
DWORD nRecvCount = 0;
char revbuf[1024];
CString filename = _T("d:\\recvdata.h264");
hFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
while(1)
{
//接收包头;
CPacketHeader header;
nRecvLen = recv(m_sockClient, (LPSTR)(LPCSTR)&header, sizeof(CPacketHeader), 0);
if (nRecvLen == SOCKET_ERROR)
{
return -1;
}
switch(header.m_nFlag)
{
case FTS_SIZE: //数据长度;
{
lDataLen = header.m_nDataLen;
}
break;
case FTS_DATA: //数据;
{
nRecvCount = recv(m_sockClient, revbuf, sizeof(revbuf), 0);
if (nRecvCount == SOCKET_ERROR)
{
break;
}
else
{
::WriteFile(hFile, revbuf, nRecvCount, &nRecvCount, NULL);
}
}
break;
case FTS_OK: //传输结束;
{
//组帧解码播放;
}
break;
default:
break;
}
}
const int PACKET_MAX_LEN = 1024;
const int DATA_MAX_LEN = 1024 - 4*sizeof(int);
typedef struct PACKET
{
int nPacketLen; //包的实际长度
int nCmd; //包的命令
int nFlag; //是否分包了
int nDataLen; //当分包的时候数据的真实长度
char szData[DATA_MAX_LEN]; //数据
}Packet,*PPacket;
//比如封装一个接口发送
int SendPacket(int nSendSocket,int nCmd,char* pData,int nLen)
{
int nTempLen = nLen;
Packet packet;
memset(&packet,0,sizeof(Packet ));
packet.nCmd = nCmd;
packet.nDataLen = nLen;
while(nTempLen > 0)
{
if(nTempLen > DATA_MAX_LEN)
{
packet.nFlag = 0; //分包
packet.nPacketLen = PACKET_MAX_LEN;
memcpy(packet.szData,pData + nLen - nTempLen,DATA_MAX_LEN);
int nSendLen = send(nSendSocket,(char*)&packet,PACKET_MAX_LEN,0);
//判断nSendLen 是否 = -1 等等....
assert(nSendLen == PACKET_MAX_LEN); //必须全部发送,可以用while的方法send
nTempLen -= DATA_MAX_LEN;
}
else
{
packet.nFlag = 1; //分包结束
packet.nPacketLen = PACKET_MAX_LEN - DATA_MAX_LEN + nTempLen;
memcpy(packet.szData,pData + nLen - nTempLen,nTempLen);
int nSendLen = send(nSendSocket,(char*)&packet,packet.nPacketLen,0);
//判断nSendLen 是否 = -1 等等....
assert(nSendLen == packet.nPacketLen); //必须全部发送,可以用while的方法send
nTempLen -= nTempLen;
}
Sleep(10); //防止发送太快
}
return 0;
}
随手写的,你可以按这种方式分包发出去
收包时,粘包 就判断 int nFlag; //是否分包了 这个去粘包 还有一个实际数据长度..... 我就不写了