文件在套接字传输中继续接收无限数据



下面的代码继续接收同一文件("/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)字节,因此您不会越过文件边界。

最新更新