我正在尝试使用C将文件发送到特定套接字;这是代码:
int send_file(char *filepath,int sock)
{
FILE *fp=fopen(filepath,"rb");
void *buff=malloc(2000);
int i=1;
while(i)
{
int bytes_read=fread(buff,1,2000,fp);
i=!(feof(fp));
int bytes_sent=0;
while(bytes_sent<bytes_read)
{
int n=send(sock,buff+bytes_sent,bytes_read-bytes_sent,0);
if(n==-1)
return -1; //failure
bytes_sent+=n;
}
}
fclose(fp);
free(buff);
return 0;
}
当我运行此程序并尝试在http://127.0.0.1:8080/的Firefox中查看文本文件时,如果文件大小超过2000字节,文件的一部分将从末尾切断。如果我发送图片,只有3/4的图片加载(从底部切断)。
该函数总是向调用者返回0。它发送的最后一块字节()s在哪里消失?在返回之前我需要冲洗一些流吗?
谢谢
编辑: 这是我的main()函数的片段:
send_file(filepath, sock);
close(sock);
return 0;
}
答案 0 :(得分:1)
这有一个标准的API!使用sendfile()
。
内核在没有上下文切换到您的线程的情况下进行复制,这实际上更有效。
答案 1 :(得分:1)
你永远不应该使用feof(),这几乎总是错误的。相反,使用fread()的返回值来确定何时读取所有内容 - 只要它不为零,就需要继续阅读和发送。在伪代码中:
while(1) {
r = fread( ... );
if ( r == 0 ) {
break;
}
send( .. );
}
答案 2 :(得分:0)
我无法看到你的程序的其余部分,但我怀疑你在关闭套接字之前已退出。
如果您的程序在套接字完成发送数据之前退出,则操作系统没有义务对剩余的未发送数据执行任何操作,并且可能会将其丢弃。
答案 3 :(得分:0)
您发布的代码对我来说没问题。 Neil说,这个问题可能存在,尽管使用微软的编译器可以正常工作。我测试它是用发送调用的存根编写的,所有数据都是“发送”的。在我看来,错误可能在于接收端。一个简单的测试就是简单地打印您在两端发送和读取的文件长度。确保recv调用获取所有已刷新的数据。
答案 4 :(得分:0)
如果您使用网络浏览器查看文件,则应在发送实际数据之前发送HTTP标头。
我只是猜测,但最有可能的是,在标题中,您将数据大小发送为2000字节。因此,即使您发送超过2000个字节,浏览器也不会期望它们,并且只显示前2000个字节。
此外,由于您正在关闭连接,因此should send Connection: close
header为客户端。
答案 5 :(得分:0)
您正在阅读网络浏览器发送给您的所有数据吗?如果你不是(这是可以理解的,如果你实际上没有编写Web服务器),那么使用未读数据调用close()
会导致TCP连接中止而不是干净关闭。
干净关机会等待发送所有未完成的数据;中止不会导致丢失数据。
出于测试目的,您应该能够通过将其放在发送功能的末尾(在您释放buff
之前)来修复它:
shutdown(sock, SHUT_WR); /* Send EOF to web browser */
while (recv(sock, buff, 2000, 0) > 0)
; /* Read and discard until we see the browser's EOF (or an error) */