在我的c#应用程序中有一些套接字通信。客户端向服务器发送一个请求(一个XML字符串),服务器用另一个XML字符串响应。
下面是运行在客户端的代码:
using (TcpClient client = new TcpClient(socket.HostName, socket.Port))
{
client.SendBufferSize = int.MaxValue;
client.ReceiveBufferSize = int.MaxValue;
Stream stream = client.GetStream();
StreamReader sr = new StreamReader(stream);
StreamWriter sw = new StreamWriter(stream);
sw.AutoFlush = true;
sw.WriteLine(requests.ToXML());
List<string> xmlStrings = new List<string>();
while (sr.Peek() > -1)
xmlStrings.Add(sr.ReadLine());
string xmlStr = string.Join("rn", xmlStrings.ToArray());
ProcessXMLResponse(xmlStr);
stream.Close();
client.Close();
}
在服务器上运行:
using (Stream stream = new NetworkStream(socket))
using (StreamReader sr = new StreamReader(stream))
using (StreamWriter sw = new StreamWriter(stream))
{
sw.AutoFlush = true;
List<string> xmlStrings = new List<string>();
while (sr.Peek() > -1)
xmlStrings.Add(sr.ReadLine());
string xmlStr = string.Join("rn", xmlStrings.ToArray());
XmlDocument xml = new XmlDocument();
xml.LoadXml(xmlStr);
string responseXML = ProcessXMLRequest(xml);
sw.WriteLine(response);
socket.Shutdown(SocketShutdown.Both);
stream.Close();
}
这段代码似乎在大多数情况下都能正常工作,但有时(可能当XML响应很大时?),客户机似乎只接收XML响应的第一部分。sr.Peek()调用返回-1,即使数据尚未全部被接收。
你知道是什么问题吗?
如果你尝试使用
sr.ReadToEnd()
代替
sr.ReadLine()
两边都有?
另外,作为一个忠告,你应该更努力地有效地利用你的资源:
using (TcpClient client = new TcpClient(socket.HostName, socket.Port))
{
client.SendBufferSize = int.MaxValue;
client.ReceiveBufferSize = int.MaxValue;
Stream stream = client.GetStream();
//generally, you should avoid calling Dispose() on an object multiple times
//don't put this in a using block as that implicitly calls Dispose() which internally calls Dispose on the stream as well
StreamReader sr = new StreamReader(stream);
//don't put this in a using block as that implicitly calls Dispose() which internally calls Dispose on the stream as well
StreamWriter sw = new StreamWriter(stream);
sw.AutoFlush = true;
sw.WriteLine("test");
List<string> xmlStrings = new List<string>();
while (sr.Peek() > -1)
xmlStrings.Add(sr.ReadLine());
string xmlStr = string.Join("rn", xmlStrings.ToArray());
//this calls stream.Dispose as well internally
sr.Close();
//actually, this also calls stream.Dispose(), but fortunately MS made it safe
sw.Close();
ProcessXMLResponse(xmlStr);
}
//At this point all IDisposable objects have been disposed of properly (TcpClient, Stream, StreamReader, StreamWriter)
//we minimized the number of stream.Dispose() calls whereas using 3 using blocks (1 for the stream, 1 for the Reader and 1 for the Writer) would have resulted in 3 calls
让我们看看MSDN中的StreamReader.Peek
:
表示下一个要读取的字符的整数,如果没有要读取的字符或者流不支持查找,则为-1。
(强调我的)
NetworkStream
不可寻:
获取一个值,该值指示流是否支持查找…此属性总是返回false。
基本上,根据文档,你的代码是坏的;我猜它是工作时,有数据随时可用(这将是一致的小vs大有效载荷的描述),但失败时,数据不是立即可用。
基本上,这里不要使用Peek
。只要读取数据,直到用完为止。如果您想尽量减少代码更改:
List<string> xmlStrings = new List<string>();
string line;
while((line = sr.ReadLine()) != null)
xmlStrings.Add(line);