从消息帧流中接收所有字节的方法冻结

时间:2014-02-12 01:20:25

标签: c# tcp

最近,我在自己的时间里学习了消息框架,并决定使用常见的解决方案,将消息前置为实际消息的长度。我使用Tcp包装器作为套接字(TcpListener,TcpClient)。

上下文 服务器和客户端都与base64编码的序列化对象进行通信。在流量较低的网络上,完整的数据似乎以一个整体到达目的地,并且可以被解码然后反序列化。但是,在具有高流量或低资源可用性的网络上,我总是得到一个FormatException,表明数据不是正确的Base64格式(或类似的错误)。以下是发送消息的方法:

    public void Send(Packet packData)
    {
        try
        {
            StreamWriter w = new StreamWriter(clientObject.GetStream());
            string s = SerializeData(packData);
            w.WriteLine(s.Length.ToString() + s);
            w.Flush();
        }
        catch (NullReferenceException) { }
        catch (IOException) { CloseObject(); }
    }

现在,这是我设计的用于在接收端读取流的方法。它似乎在while循环中冻结:

    private string ReceiveAllDataFromStream(StreamReader r)
    {
        int a = 0;
        int b = 0;
        string str = null;
        try
        {
            str = r.ReadLine();
            // find out how many chars are integers, then get the value in int. (this is the length of the message)
            foreach (char f in str) { if (int.TryParse(f.ToString(), out a)) { b++; } else { break; } }
            // reuse "a", it doesn't actually contain the result of the TryParse method called above
            a = int.Parse(str.Substring(0, b));
            // remove these chars (the ints) from the message
            str = str.Remove(0, b);
            // calculate how many chars need to be received to complete this message
            int msgRemaining = a - str.Length;
            int msgAcquired = str.Length;
            if (msgAcquired != a)
            {
                // where i believe the freeze is caused
                while (msgAcquired != a)
                {
                    // make a call to supposedly retreieve these last few chars
                    string s = r.ReadLine();
                    // insert as much of the new string received as "msgRemaining" demands
                    str.Insert(0, s.Substring(0, msgRemaining));
                    // add the total length of the inserted string to the amount already aquired, continue with loop
                    msgAcquired = msgAcquired + s.Substring(0, msgRemaining).Length;
                }
            } return str;
        }
        catch (FormatException) { System.Windows.Forms.MessageBox.Show(b.ToString() + "|" + str.Substring(0, b)); return null; }
    }

当我说它冻结时,我的意思是应用程序进入空闲状态(UI未被阻止,但我相信这是因为此方法在另一个线程上运行)。我的方法有什么问题,我该如何修复它?

谢谢。

0 个答案:

没有答案