我的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("\r\n", 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("\r\n", 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。
知道问题可能是什么?
答案 0 :(得分: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("\r\n", 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
答案 1 :(得分:0)
让我们看一下StreamReader.Peek
in MSDN:
表示要读取的下一个字符的整数,如果没有要读取的字符,或者如果流不支持,则为-1。
(强调我的)
NetworkStream
is not seekable:
获取一个值,该值指示流是否支持搜索...此属性始终返回false。
基本上,根据文档,你的代码被破坏了;当有数据随时可用时(这与小型和大型有效负载描述一致),我猜测它正在工作,但是当数据不能立即可用时就会失败。
基本上,请勿在此使用Peek
。只需读取数据,直到用完为止。如果您想最小化代码更改:
List<string> xmlStrings = new List<string>();
string line;
while((line = sr.ReadLine()) != null)
xmlStrings.Add(line);
但我个人会以非常不同的方式实现它。