下面的代码继续接收同一文件("/tmp/frame")中的数据,当真正的目的是接收在单独的文件。似乎服务器开始接收一个文件并没有关闭,继续接收以下文件的数据。
(代码中的注释解决了问题,但延迟了文件的传输)
发送者:screenshot ptr_screen;
CHAR Block[4096], buffer[512];
int BytesRead, iResult;
for (;;) {
memset(Block, 0, sizeof(Block));
memset(buffer, 0, sizeof(buffer));
ptr_screen.Start();
FILE *fp = fopen("screen.jpg", "rb");
if (!fp) { break; }
fseek(fp, 0, SEEK_END);
int32_t file_size = ftell(fp);
fseek(fp, 0, SEEK_SET);
iResult = send(socket_, (char*)&file_size, sizeof(file_size), 0);
if (iResult == SOCKET_ERROR) { fclose(fp); break; }
while (file_size > 0) {
BytesRead = fread(Block, 1, sizeof(Block), fp);
if (BytesRead <= 0) { break; }
iResult = send(socket_, Block, BytesRead, 0);
if (iResult != BytesRead) { break; }
file_size -= BytesRead;
}
fflush(fp);
fclose(fp);
//if (recv_to(socket_, buffer, sizeof(buffer), 0, 5000) <= 0)
//break;
}
接收机:
int iResult;
char Block[512];
int32_t file_size;
for(;;) {
FILE* fp = fopen("/tmp/frame", "wb");
if(!fp) { break; }
memset(Block, 0, sizeof(Block));
iResult = recv_to((char*)&file_size, sizeof(file_size), 10);
if(iResult <= 0 ) { break; }
while(file_size > 0) {
iResult = recv_to(Block, sizeof(Block), 10);
if(iResult <= 0) { break; }
if(fwrite(Block, 1, iResult, fp) != (unsigned)iResult) { return; }
file_size -= iResult;
}
fclose(fp);
system("mv /tmp/frame /tmp/stream.jpg");
//send(socket_, "OK", strlen("OK"), 0); // response
}
TCP是一个流协议。接收方通常不会接收到与发送方相同的数据块——你会得到基本上是任意分解的数据块。
特别是,当发送方发送文件的最后一块,然后立即发送新文件的大小和第一个块时,接收者完全有可能接收到下一个文件的最后一个块、大小和第一个块的部分,所有这些都卷在一起。file_size
会变成负的,这一次会让你脱离内环。然后,您将从下一个文件的中间读入file_size
中的一些随机数据。它可能只是碰巧形成了一个非常大的整数,这就是为什么你的内循环似乎不再退出的原因。
在内部循环中读取max(sizeof(Block), file_size)
字节,因此您不会越过文件边界。