当两台电脑要通过网络)传输数据的时候,应用层必须要制定好自己的头部,最简单的头部可以是这样(以传输图片为例):
起始标志0xFFEF(short类型,表明这是一个包的开头)+图片数据长度(int类型,4个字节)+图片数据(完整的图片数据)
发送端和接收端的C代码大致如下:
发送端代码:
void sendPic(int len, char* picData) // len是图片大小, picData是图片在内存中的起始地址{
int totalLen = sizeof(short) + sizeof(int) + len; //这是整个包长
char* appData = new char[totalLen ];
memcpy(appData , htons(0xFFEF), sizeof(short));
memcpy(appData + sizeof(short), htohl(len), sizeof(int));
memcpy(appData + sizeof(short) + sizeof(int), picData, len);
send(s, appData, totalLen, 0);
}
接收端代码:
#define BUFSIZE 1024*1024
#define ONCE_RCV_LEN 1500
void recvPic()
{
// 下面分配的内存是用于接收数据的,会循环使用
char* picPacket = new char[BUFSIZE ];
int readPos = 0; // 读数据的位置
int writePos = 0; // 写数据的位置
// 下面这个循环就是用于循环接收图片的
while(true)
{
int len = recv(s, picPacket + writePos, ONCE_RCV_LEN, 0);
writePos += len;
// 下面的循环是用来找到数据包的起始位置的,有时会有一些无效数据存在,需要跳过
while( ntos(short(picPacket + readPos)) != 0xFFEF)
readPos++;
readPos += sizeof(short);
int picLen = ntohl(int(picPacket + readPos)); // 取出图片长度
readPos += sizeof(int);
if(writePos - readPos < picLen) // 当图片尚未完全接收完的时候,要继续接收剩余部分
{
len = recv(s, picPacket + writePos, picLen - (writePos - readPos));
writePos += len;
}
displayPic(picPacket + readPos, picLen); //这个函数用来显示图片的,只是个示例
readPos += picLen;
// 当剩余缓存不够接收下一批数据的时候,将尚未读取的数据copy到接收缓存头部
if(writePos + ONCE_RCV_LEN > BUFSIZE)
{
memcpy(picPacket, picPacket + readPos, writePos - readPos);
readPos = 0;
writePos = writePos - readPos;
}
}
}