使用套接字c#client / server发送文件

时间:2014-06-19 13:56:10

标签: c# sockets

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

客户端 - 发送:

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();
}

接收代码:

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());
    }
}

任何想法?

2 个答案:

答案 0 :(得分:1)

您的主要问题是,您希望DataAvailable == false表示不再有更多数据。事实并非如此。 DataAvailable表示数据是否可用现在。这并不意味着将来某个时候不再可用。

如果您要发送和接收任何类型的数据,发送方必须有某种方式告诉接收方消息的结束位置。一般来说,有两种方法可以做到这一点:

  1. 发送一个标题,告知要跟踪的字节数。
  2. 在发送完所有其他数据后发送“消息结束”数据包。
  3. 使用文本协议时,通常使用第二个选项:发送消息,并使用换行符终止。这标志着信息的终结。

    发送二进制数据时,通常使用第一种方法。该标题可以是简单的四个字节,表示文件的长度。所以在你的情况下,你会写一些类似的东西:

    // 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.
    

答案 1 :(得分:0)

为什么不在发件人端执行此操作:

fileStream.CopyTo(networkStream);

更简单:)

在接收方,您不能认为DataAvailable = false表示没有更多数据。完成socket.Shutdown(SocketShutdown.Send)后发送方最好关闭连接,并且接收方继续读取直到0返回。

发件人方:

  1. 服务器发送文件
  2. 服务器调用socket.Shutdown(SocketShutdown.Send);
  3. 服务器执行socket.Receive(xxx)等待正常断开连接
  4. Socket.Close();
  5. 接收方:

    1. 从网络读取,直到读取返回0
    2. 关闭文件流(文件已完成)
    3. 致电socket.Shutdown(SocketShutdown.Both)
    4. Socket.Close();
    5. 但是,您仍有一个缺陷:由于网络故障,套接字可能已断开连接。唯一知道的方法是先发送文件大小(在发送文件之前)