2

我尝试使用 c 和套接字编写我自己的下载管理器,现在发生了一些奇怪的事情,我真的无法解释为什么。

所以我要做的是:我创建套接字,连接到服务器,创建并发送一个 GET 请求。到目前为止一切都很好。下载开始,完成后,我在 byte(char) 数组中搜索 '\n\r\n' 以到达标题的末尾(进一步查找消息正文的开头)。从那里我将 msg_size-(header_end+1) 字节写入文件。结果文件的字节大小与我定期下载文件的字节大小完全相同。但是当我尝试提取它时,它会在“文件意外结束”上出错,而​​另一个版本提取得很好。

有人可能对此有解释吗,我也可以提供代码,我只是不确定问题出在哪里,所以我首先尝试用语言表达问题。我已经尝试了“wb”和“w”标志。

服务器也没有指定分块传输或压缩编码。虽然它是 http/1.1。

谢谢!

编辑:所以这是服务器标题:

HTTP/1.1 200 OK
Date: Mon, 20 May 2013 16:33:26 GMT
Server: Apache/2.2.9 (Debian)
Last-Modified: Sun, 17 Jan 2010 18:17:39 GMT
ETag: "3ba006-29b376-47d60407b56c0"
Accept-Ranges: bytes
Content-Length: 2732918
Content-Type: application/x-gzip

编辑2;这就是我接收和写入文件的方式:

    memset(file,0,file_size);
    arg[1]=recv(socketfd,file,file_size,0);
    int mstart=0;
    while(file[mstart]!='\n' ||file[mstart+1]!='\r'|| file[mstart+2]!='\n'){
       mstart++;
    }
    mstart+=3;
    fsize=file_size;
    int fsize=file_size-mstart;       //file_size from Response Header
    fwrite(&(file[mstart]),1,fsize,fd);
    fclose(fd)

好的,这很有意义,所以我现在尝试了这个:(编辑)错误,但这也不起作用:

  fd=fopen(file_name,"wb");  
  memset(file,0,file_size);
  recv(socketfd,file,3,0);
  while(1==1){
    if(file[0]=='\n' ||file[1]=='\r'|| file[2]=='\n'){
      recv(socketfd,file,3,0);
    }else{
      break;
    }
  }
  arg[1]=recv(socketfd,file,file_size,MSG_WAITALL);
  fwrite(file,1,file_size,fd);
  fclose(fd);

但它现在仍在工作

最后!这工作知道,非常感谢你!

  fd=fopen(file_name,"w");  
  memset(file,0,file_size);
  recv(socketfd,file,3,0);
  while(file[0]!='\n' ||file[1]!='\r'|| file[2]!='\n'){
      recv(socketfd,file,3,0);
  }
  arg[1]=recv(socketfd,file,file_size,MSG_WAITALL);
  fwrite(file,1,file_size,fd);
  fclose(fd);
4

1 回答 1

1

您的文件读取逻辑不太正常。您首先需要读取一些固定数量,并解析该固定数量以找到标题的结尾。然后解析标题以查找内容长度。然后,您已经读取的超出标题末尾的任何数据都将作为文件的第一部分写出。文件的其余部分是内容长度减去您所写的内容。您必须从套接字读取更多字节并写入文件。

您的问题是您没有正确使用内容长度标头(您已从先前的 HEAD 请求中提取)。它指示标头之后的传输大小,而不是整个响应的长度。

文件看起来大小正确的原因是您正在写出正确的字节数,但是您正在读取从套接字读取的字节的末尾(因为您已经mstart向前调整超过了标头的末尾)。

于 2013-05-20T17:00:16.807 回答