2014-06-19 98 views
-1

我想使用套接字发送文件..它的工作与几个字节文件没有更多...如何解决这个问题? 这是一个客户端/服务器程序 我试图发送至少50 MB。发送带有套接字的文件c#客户端/服务器

的客户端,发送:

System.Net.Sockets.TcpClient tcpClient = new 
    System.Net.Sockets.TcpClient(); 

tcpClient.Connect(recipientIP, FTPPORTNO); 
int BufferSize = tcpClient.ReceiveBufferSize; 
NetworkStream nws = tcpClient.GetStream(); 

FileStream fs; 
fs = new FileStream(filename, FileMode.Open, 
    FileAccess.Read); 
byte[] bytesToSend = new byte[fs.Length]; 
int numBytesRead = fs.Read(bytesToSend, 0, 
    bytesToSend.Length); 
int totalBytes = 0; 
for (int i = 0; i <= fs.Length/BufferSize; i++) 
{ 
    //---send the file--- 
    if (fs.Length - (i*BufferSize) > BufferSize) 
    { 
     nws.Write(bytesToSend, i*BufferSize, 
      BufferSize); 
     totalBytes += BufferSize; 
    } 
    else 
    { 
     nws.Write(bytesToSend, i*BufferSize, 
      (int) fs.Length - (i*BufferSize)); 
     totalBytes += (int) fs.Length - (i*BufferSize); 
    } 
    fs.Close(); 
} 

的Recieving代码:

try 
{ 
    //---get the local IP address--- 
    System.Net.IPAddress localAdd = 
     System.Net.IPAddress.Parse(
      ips.AddressList[0].ToString()); 
    //---start listening for incoming connection--- 
    System.Net.Sockets.TcpListener listener = new 
     System.Net.Sockets.TcpListener(localAdd, 
      FTPPORTNO); 
    listener.Start(); 
    //---read incoming stream--- 
    TcpClient tcpClient = listener.AcceptTcpClient(); 
    NetworkStream nws = tcpClient.GetStream(); 
    //---delete the file if it exists--- 
    if (File.Exists("c:\\temp\\" + filename)) 
    { 
     File.Delete("c:\\temp\\" + filename); 
    } 
    //---create the file--- 
    fs = new System.IO.FileStream("c:\\temp\\" + filename, 
     FileMode.Append, FileAccess.Write); 
    int counter = 0; 
    int totalBytes = 0; 
    do 
    { 
     //---read the incoming data--- 
     int bytesRead = nws.Read(data, 0, 
      tcpClient.ReceiveBufferSize); 
     totalBytes += bytesRead; 
     fs.Write(data, 0, bytesRead); 
     //---update the status label--- 
     ToolStripStatusLabel1.Text = "Receiving " + 
             totalBytes + " bytes...."; 
     Application.DoEvents(); 
     counter += 1; 
    } while (nws.DataAvailable); 
    ToolStripStatusLabel1.Text = "Receiving " + totalBytes 
            + " bytes....Done."; 
    fs.Close(); 
    tcpClient.Close(); 
    listener.Stop(); 
} 
catch (Exception ex) 
{ 
    MessageBox.Show(ex.ToString()); 
} 

服务器代码:

public void SendMessage (string message) 
{ 
    //---adds a linefeed char--- 
    message += "\n"; 
    try 
    { 
     //---send the text--- 
     System.Net.Sockets.NetworkStream ns; 
     lock (client.GetStream()) 
     { 
      ns = client.GetStream(); 
      byte[] bytesToSend = 
       System.Text.Encoding.ASCII.GetBytes(message); 
      //---sends the text--- 
      ns.Write(bytesToSend, 0, bytesToSend.Length); 
      ns.Flush(); 
     } 
    } 
    catch (Exception ex) 
    { 
     MessageBox.Show(ex.ToString()); 
    } 
} 

什么想法?

+0

您是否试图做到这一点? [检查此](http://code.msdn.microsoft.com/windowsdesktop/Fixed-size-large-file-dfc3f45d) –

+0

请编辑您的问题,并格式化代码。你现在拥有的东西几乎是不可读的。 –

+0

好吧......我应该把它分成块或什么东西? – user3379482

回答

1

您的主要问题是您期望DataAvailable == false意味着不再有数据即将到来。事实并非如此。 DataAvailable表示数据是否可用现在。这并不意味着未来将不再有可用的空间。

如果您正在发送和接收任何类型的数据,发送者必须通过某种方式告诉接收者邮件的末尾在哪里。一般来说,有两种方法可以做到这一点:

  1. 发送一个标题,告诉它有多少个字节。
  2. 发送完所有数据后发送“消息结束”数据包。

对于文本协议,通常使用第二个选项:发送消息并以换行符终止。这标志着消息的结束。

发送二进制数据时,通常使用第一种方法。这个头文件可以像四个字节那样简单,就是说文件有多长。所以你的情况,你会写这样的:

// tell receiver how many bytes are coming 
byte[] lengthData = BitConverter.GetBytes[fs.Length]; 
nws.Write(lengthData, 0, lengthData.Length); 
// then send the file 

的接收器,然后,需要读取前四个字节,转换为整数,然后读取的字节数。只有在读取了很多字节的情况下才能知道它已经到达文件的末尾。

// read length 
byte[] lengthData = new byte[4]; 
bytesRead = nws.Read(lengthData, 0, 4); 
// I assume here that it got all four bytes. In your code, you'll want to 
// make sure that you got four bytes before moving on. 
int bytesToRead = BitConverter.ToInt32(lengthData, 0); 
// Now start your reading loop, and read until the total number of bytes read 
// is equal to the bytesToRead value above. 
+0

有趣......一个伟大的!我会尝试一下 – user3379482

0

你为什么不只是这样做的发件人结束:

fileStream.CopyTo(networkStream); 

简单多了:)

在接收端,你不能假设DataAvailable = false意味着没有更多的数据。当完成socket.Shutdown(SocketShutdown.Send)时,发送方关闭连接并且接收方继续读取,直到返回0为止。

发送方:

  1. 服务器发送文件
  2. 服务器调用socket.Shutdown(SocketShutdown.Send);
  3. 服务器确实socket.Receive(xxx)等待优美断开
  4. Socket.Close();

接收侧:

  1. 从网络读取,直到读返回0
  2. 关闭文件流(文件已完成)
  3. 呼叫socket.Shutdown(SocketShutdown.Both)
  4. Socket.Close();

但是,你仍然有一个缺陷:该插座可能已经由于网络故障而断开连接。唯一的方法是先发送文件大小(在发送文件之前)

相关问题