最近,我在自己的时间里学习了消息框架,并决定使用常见的解决方案,将消息前置为实际消息的长度。我使用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未被阻止,但我相信这是因为此方法在另一个线程上运行)。我的方法有什么问题,我该如何修复它?
谢谢。