所以我需要从服务器回收一个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,所以我不知道怎么能结束它。(或者在这种情况下我可能不需要第二个循环)。
编辑:我不能发送文件的长度,因为协议我跟随
答案 0 :(得分:2)
TCP是一种用于在每个方向上传输单个非结构化八位字节流的协议。关闭连接(即EOF)是TCP向对等方发信号通知此连接中不再发送数据的唯一方法。如果您需要一种不同的方式,因为您需要区分同一TCP连接中的多个消息,那么您需要使用可以指定此类消息边界的应用程序级协议。这通常通过固定的消息大小来完成,在消息前面加上长度或特殊的边界标记。
答案 1 :(得分:-1)
如果无法在协议中嵌入有效负载大小,则必须通过关闭套接字或检查超时来识别EOF。您可以使用select功能并为其设置超时,请参阅此处Using select and recv to obtain a file from a web server through a socket和https://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。