如何在没有eof的情况下重新开始直到recv?

时间:2016-12-17 11:20:52

标签: c sockets tcp

所以我需要从服务器回收一个html文件到客户端,文件比缓冲区大,所以我发了几个。这就是为什么我在recv时有这个循环

while (i = recv(s, buf, TAM_BUFFER, 0)) {
            if (i == -1) {
                perror(argv[0]);
                fprintf(stderr, "%s: error reading result\n", argv[0]);
                exit(1);
            }
            while (i < TAM_BUFFER) {
                j = recv(s, &buf[i], TAM_BUFFER - i, 0);
                if (j == -1) {
                    perror(argv[0]);
                    fprintf(stderr, "%s: error reading result\n", argv[0]);
                    exit(1);
                }
                i += j;
            }
            /* Print out the file line by line. */
            printf("%s", buf);
}

发送看起来像这样:

while (fgets(buf, sizeof(buf), fp)){
                    if (send(s, buf, TAM_BUFFER, 0) != TAM_BUFFER) errout(hostname);
                }

问题是循环永远不会结束,因为它没有收回eof而且我从不0,它只是在那里被阻止。 我不能发送eof,因为在他收回整个文件后,客户端会要求另一个文件。

如果循环被阻塞的时间超过5秒,我尝试发送一个SIGALRM,但它没有按预期工作,因为循环不会停止,并且会抛出错误。

另外我怎么能够比TAM_BUFFER少得多?(在发送中,更改TAM_BUFFER - &gt; strlen(buf))我知道我需要更改内部循环,但是后来生病了同样的问题,j永远不会是0,所以我不知道怎么能结束它。(或者在这种情况下我可能不需要第二个循环)。

编辑:我不能发送文件的长度,因为协议我跟随

3 个答案:

答案 0 :(得分:2)

TCP是一种用于在每个方向上传输单个非结构化八位字节流的协议。关闭连接(即EOF)是TCP向对等方发信号通知此连接中不再发送数据的唯一方法。如果您需要一种不同的方式,因为您需要区分同一TCP连接中的多个消息,那么您需要使用可以指定此类消息边界的应用程序级协议。这通常通过固定的消息大小来完成,在消息前面加上长度或特殊的边界标记。

答案 1 :(得分:-1)

如果无法在协议中嵌入有效负载大小,则必须通过关闭套接字或检查超时来识别EOF。您可以使用select功能并为其设置超时,请参阅此处Using select and recv to obtain a file from a web server through a sockethttps://stackoverflow.com/a/30395738/4490542

答案 2 :(得分:-2)

所以我设法让它按照我想要的方式工作:

i=1;
while (i) {
    alarm(TIMEOUT);
    i=recv(s, buf, TAM_BUFFER, 0);
    if (i == -1) {
        if (errno == EINTR){
            break;
        }
        else{
            perror(argv[0]);
            fprintf(stderr, "%s: error reading result\n", argv[0]);
            exit(1);
        }
    }
}

它会在关闭的情况下退出循环,但是如果它被阻挡这么长时间就会中断。 EINTR表示操作被中断,以防另一个错误导致recv returnin -1。