如何确保完全读取流?

时间:2015-11-02 12:58:37

标签: c#

我正在使用Network Stream, TcpListener and Sockets

我想确保接收方收到发送方的所有数据。

我有以下代码接收器

private void StartReciever()
{
    util.LoadSettings();

    string tcpIpAddress = util.svrSettings["IpAddress"];
    string port = util.svrSettings["Port"];
    string outDir = util.svrSettings["isOutput"];

    new Thread(
    () =>
    {
        if (!File.Exists(util.settingFile))
            Logger("Please setup the services first.");
        else
        {
            try
            {
                IPAddress ipAddress = IPAddress.Parse(tcpIpAddress);
                TcpListener tcpListener = new TcpListener(ipAddress, Convert.ToInt32(port));

                tcpListener.Start();

                Logger("\nWaiting for a client to connect...");

                //blocks until a client connects
                Socket socketForClient = tcpListener.AcceptSocket();

                Logger("\nClient connected");

                //Read data sent from client
                NetworkStream networkStream = new NetworkStream(socketForClient);
                int bytesReceived, totalReceived = 0;

                string fileName = "testing.txt";

                byte[] receivedData = new byte[10000];
                do
                {
                    bytesReceived = networkStream.Read
                        (receivedData, 0, receivedData.Length);
                    totalReceived += bytesReceived;
                    Logger("Progress of bytes recieved: " + totalReceived.ToString());
                    if (!File.Exists(fileName))
                    {
                        using (File.Create(fileName)) { };
                    }

                    using (var stream = new FileStream(fileName, FileMode.Append))
                    {
                        stream.Write(receivedData, 0, bytesReceived);
                    }

                }
                while (bytesReceived != 0);
                Logger("Total bytes read: " + totalReceived.ToString());

                socketForClient.Close();
                Logger("Client disconnected...");

                tcpListener.Stop();
            }
            catch (Exception ex)
            {
                // Error : "Only one usage of each socket address (protocol/network address/port) is normally permitted"     
                Logger("There is some error: " + ex.Message); 
            }
        }
    }).Start();
}

如何在do-while循环执行后确保我的代码?

发件人代码:

private static void SendData(string tcpIpAddress, string port, string filename)
{
    new Thread(
      () =>
      {
          TcpClient tcpClient = new TcpClient(tcpIpAddress, Convert.ToInt32(port));
          //const int bufsize = 8192;
          const int bufsize = 10000;
          var buffer = new byte[bufsize];
          NetworkStream networkStream = tcpClient.GetStream();

          using (var readFile = File.OpenRead(filename))
          {
              int actuallyRead;
              while ((actuallyRead = readFile.Read(buffer, 0, bufsize)) > 0)
              {
                  networkStream.Write(buffer, 0, actuallyRead);
              }
          }
      }).Start();
}

2 个答案:

答案 0 :(得分:3)

  

如何在do-while循环执行后确保我的代码?

这里很容易,因为您可以关闭发送方的连接,这将导致接收方读取零字节并终止循环。

实际上你忘了清理发件人了。处置所有资源。这解决了这个问题。

您的代码将受益于Code Review SE。我看到十几个问题对这个问题无关紧要。这将是一个改善自己的好方法。

例如,您可以使用Stream.Copy替换复制循环。

答案 1 :(得分:0)

通常的方式我已经看到这样做是为了预先发送要发送的字节数的数据。这样接收器就知道数据包已被读取。即使网络中断或发送者不间断地发送其他内容。

请注意,在分配读取缓冲区之前,您还可以读取前8个字节(如果Int32将执行此操作,则读取4个字节),这有助于优化缓冲区大小

另一种常见的方法是使用特定的终止符,但是你必须保证你发送的任何内容都不能包含终结符