将文件发送到套接字

时间:2010-01-29 19:35:55

标签: c networking

我正在尝试使用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;
 }

6 个答案:

答案 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) */