C# 套接字流不包含整个响应
我的c#应用程序中有一些套接字通信。客户端向服务器发送一个请求(一个XML字符串),服务器用另一个XML字符串进行响应 以下是在客户端上运行的代码:C# 套接字流不包含整个响应,c#,xml,sockets,stream,C#,Xml,Sockets,Stream,我的c#应用程序中有一些套接字通信。客户端向服务器发送一个请求(一个XML字符串),服务器用另一个XML字符串进行响应 以下是在客户端上运行的代码: using (TcpClient client = new TcpClient(socket.HostName, socket.Port)) { client.SendBufferSize = int.MaxValue; client.ReceiveBufferSize = int.MaxValue; Stream stre
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();
}
使用(TcpClient client=newtcpclient(socket.HostName,socket.Port))
{
client.SendBufferSize=int.MaxValue;
client.ReceiveBufferSize=int.MaxValue;
Stream=client.GetStream();
StreamReader sr=新的StreamReader(流);
StreamWriter sw=新StreamWriter(流);
sw.AutoFlush=true;
sw.WriteLine(requests.ToXML());
List xmlStrings=新列表();
while(sr.Peek()>-1)
Add(sr.ReadLine());
字符串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();
}
使用(流=新的网络流(套接字))
使用(StreamReader sr=新StreamReader(stream))
使用(StreamWriter sw=新StreamWriter(流))
{
sw.AutoFlush=true;
List xmlStrings=新列表();
while(sr.Peek()>-1)
Add(sr.ReadLine());
字符串xmlStr=string.Join(“\r\n”,xmlStrings.ToArray());
XmlDocument xml=新的XmlDocument();
LoadXml(xmlStr);
字符串responseXML=ProcessXMLRequest(xml);
sw.WriteLine(响应);
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("\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
使用(TcpClient client=newtcpclient(socket.HostName,socket.Port))
{
client.SendBufferSize=int.MaxValue;
client.ReceiveBufferSize=int.MaxValue;
Stream=client.GetStream();
//通常,应该避免多次对对象调用Dispose()
//不要把它放在using块中,因为它隐式调用Dispose(),而Dispose()也在流上内部调用Dispose
StreamReader sr=新的StreamReader(流);
//不要把它放在using块中,因为它隐式调用Dispose(),而Dispose()也在流上内部调用Dispose
StreamWriter sw=新StreamWriter(流);
sw.AutoFlush=true;
软件写入线(“测试”);
List xmlStrings=新列表();
while(sr.Peek()>-1)
Add(sr.ReadLine());
字符串xmlStr=string.Join(“\r\n”,xmlStrings.ToArray());
//这将在内部调用stream.Dispose
高级关闭();
//实际上,这也调用stream.Dispose(),但幸运的是MS使其安全
sw.Close();
ProcessXMLResponse(xmlStr);
}
//此时,所有IDisposable对象都已正确处置(TcpClient、Stream、StreamReader、StreamWriter)
//我们最小化了stream.Dispose()调用的数量,而使用3个使用块(1个用于流,1个用于读卡器,1个用于写卡器)将导致3个调用
让我们看看:
表示要读取的下一个字符的整数,如果没有要读取的字符或流不支持查找,则为-1
(强调矿山)
网络流
:
获取一个值,该值指示流是否支持查找。。。此属性始终返回false
基本上,根据文档,您的代码已损坏;我猜当数据随时可用时(这与小负载与大负载的描述一致),它会工作,但当数据不立即可用时,它会失败
基本上,不要在这里使用Peek
。只需读取数据,直到用完为止。如果要尽量减少代码更改,请执行以下操作:
List<string> xmlStrings = new List<string>();
string line;
while((line = sr.ReadLine()) != null)
xmlStrings.Add(line);
List xmlStrings=new List();
弦线;
而((line=sr.ReadLine())!=null)
添加(行);
但就我个人而言,我的实现方式会有很大不同。可能是因为数据尚未完全发送/接收。尝试提前发送长度,并等待socket.Available==length.ReadToEnd对此不受支持,并且它会无限期地阻塞。