2013-12-19 42 views
0

在我的服务器程序中,我应该从客户端取一个文件,但这可以是任意大小,所以我怎么才能知道它的大小,以便我可以为它设置缓冲区大小。我试过这个代码,但最后我只是得到1kb文件夹,这是不工作了。寻找传入文件的大小

   private void checkRequest() 
     { // Checks if request is a download or upload request and calls function that fits. 
... 
... 
... 
      else if (Request.Contains("Upload")) //If request is upload (Client wants to upload) 
     { 
      info = Request; 
      nickName = Request.Substring(0, Request.IndexOf("Upload")); //Takes nickname 
      info = info.Replace(nickName, ""); //Takes nickName of the client and deletes 
      info = info.Replace("Upload", ""); //Deletes request. 

      if (!sList.Contains(nickName)) //If nick name is unique 
      { 
       info = info.Substring(0, info.IndexOf("end")); 

       sList.Add(nickName); //Adds nick name into a list. 
       Receive(info); 
      } 
     } 
     else 
     { 
      serverSocket.Close(); // If any problem occurs server becomes offline. 
     } 
    } 
    private void Receive(string receivedFileName) 
    { 
     byte[] buffer = new byte[1024]; //This is the part I can't fit anything. 
     activity.AppendText("File downloading to " + fileDir + " destination"); 
     while (tempSocket.Receive(buffer) != 0) 
     { 
      File.WriteAllBytes(fileDir + "//" + fileName, buffer); //Creates a new file or overwrites it. 

     } 
     activity.AppendText("File downloaded..."); // Updates activity log(text box.) 

    } 
+0

'tempSocket.Receive(缓冲)'不garunteed经常阅读'buffer.Length'字节,你需要检查从'Receive'的结果,只使用很多'buffer'中的字节。同样来自[WriteAllBytes]上的MSDN(http://msdn.microsoft.com/en-us/library/system.io.file.writeallbytes%28v=vs.110%29.aspx)“*创建一个新文件,将指定的字节数组写入文件,然后关闭该文件。**如果目标文件已经存在,它将被覆盖**。*“,您需要使用附加内容而不是覆盖文件。 –

回答

1

你做File.WriteAllBytes()函数调用之前,写了Int64拿出来与文件长度的插座。

然后让您的客户先查找该长度,并适当设置缓冲区。

备注

如果你想在TCP流仅从文件中包含的数据,你可以有一个包含多个套接字协议:

  • 控制插座 - 这个插座就会等待连接告诉它一个文件需要上传。一旦客户端连接,客户端将传递它的信息,如file size。然后服务器将用新端口的端口进行响应。 (数据插座
  • 数据套接字 - 当客户端连接到此套接字时,它会立即发送整个文件。一旦服务器收到约定的字节数,它将关闭套接字。
+0

在数据之前发送大小是个不好的做法,因为它打破了流设计。流不知道什么时候它会结束,直到它结束... –

+0

@WouterHuysentruit如果你没有办法告诉文件何时完成传输,除非另一端在最后关闭流,或者检查一个代表流结束的特殊模式(但在发送之前,您必须确保该文件不包含该模式)。如果你打开这个流,你可以发送一个任意大小的文件。正如你所说的,数据流不知道它什么时候结束直到它结束,所以你必须添加元数据来告诉接收器多少期望。 –

+0

哦错过了这个流保持打开的事实。 –

0

由于您将套接字打开,所以您确实必须首先按照Andrew的建议发送文件的大小。

但即使如此,也不要将所有内容读入内存中的数组,而是考虑使用FileStream并将数据直接写入磁盘中。

喜欢的东西:

private void Receive(string receivedFileName) 
{ 
    byte[] buffer = new byte[1024]; 
    // receive file size 
    if (tempSocket.Receive(buffer, sizeof(ulong), SocketFlags.None) != sizeof(ulong)) 
    { 
     // failed to receive the size 
     return; 
    } 
    ulong fileSize = BitConverter.ToUInt64(buffer, 0); 
    // receive file data 
    activity.AppendText("File downloading to " + fileDir + " destination"); 
    using (FileStream stream = new FileStream(fileDir + "//" + fileName, FileMode.Create, FileAccess.Write) 
    { 
     ulong totalBytesReceived = 0; 
     while (totalBytesReceived < fileSize) 
     { 
      int bytesReceived = tempSocket.Receive(buffer); 
      if (bytesReceived > 0) 
      { 
       stream.Write(buffer, 0, bytesReceived); 
       totalBytesReceived += (ulong)bytesReceived; 
      } 
      else 
      { 
       Thread.Sleep(1); 
      } 
     } 
    } 
    activity.AppendText("File downloaded..."); // Updates activity log(text box.) 
}