问题描述
写一个TCP客户端,解析server发送的xml协议流,xml协议很简单,类似<?xmlversion="1.0"encoding="utf-8"?><bookname=""data=""price=""><result></result></book>一行一句。用的StreamReader(TcpClient.GetStream).ReadToEnd()无法接受消息,ReadLine就可以接受。代码部分如下privatevoidbutton1_Click(objectsender,EventArgse){serverThread=newThread(newThreadStart(Connection));serverThread.Start();}privatevoidConnection(){try{IPAddressipAddress=IPAddress.Parse(txtIP.Text);Int32port=Int32.Parse(txtPort.Text);IPEndPointipe=newIPEndPoint(ipAddress,port);myclient=newTcpClient();myclient.Connect(ipe);log.Info("发起客户端连接");//stringhostName=Dns.GetHostEntry(ipAddress).HostName;//myclient=newTcpClient(hostName,port);}catch{MessageBox.Show("没有连接服务器!");log.Info("没有连接服务器");return;}listBox1.Items.Add("客户端连接服务器!");log.Info("客户端成功连接");networkStream=myclient.GetStream();streamReader=newStreamReader(networkStream);streamWriter=newStreamWriter(networkStream);//创建接收信息线程,并启动recvThread=newThread(newThreadStart(RecvData));recvThread.Start();}privatevoidRecvData(){//strings=streamReader.ReadLine();strings=streamReader.ReadToEnd();///用ReadLine可以获得数据,用ReadToEnd无反应,但是根据协议形式要解析必须全部读取完,一次读一行不方便。}
解决方案
本帖最后由 walle_panpan 于 2016-06-22 10:16:24 编辑
解决方案二:
顶一下,在线等回复
解决方案三:
ReadToEnd要到‘TCP连接断开’才结束。如果你是短连接,可以用ReadToEnd。如果你要重复使用TCP连接,那么你最好定义通讯格式。对Xml负载来说,ReadLine不太合适,因为Xml可以是空行/换行无关的。而且具体要读多少行,并不好处理。
解决方案四:
引用2楼Forty2的回复:
ReadToEnd要到‘TCP连接断开’才结束。如果你是短连接,可以用ReadToEnd。如果你要重复使用TCP连接,那么你最好定义通讯格式。对Xml负载来说,ReadLine不太合适,因为Xml可以是空行/换行无关的。而且具体要读多少行,并不好处理。
TCP连接是要一直保持的,通讯格式也是确定的,这样的话我就无法使用ReadToEnd了,用ReadLine好像比较麻烦,一行一行读再拼成xmlstring吗
解决方案五:
引用3楼walle_panpan的回复:
Quote: 引用2楼Forty2的回复:
ReadToEnd要到‘TCP连接断开’才结束。如果你是短连接,可以用ReadToEnd。如果你要重复使用TCP连接,那么你最好定义通讯格式。对Xml负载来说,ReadLine不太合适,因为Xml可以是空行/换行无关的。而且具体要读多少行,并不好处理。TCP连接是要一直保持的,通讯格式也是确定的,这样的话我就无法使用ReadToEnd了,用ReadLine好像比较麻烦,一行一行读再拼成xmlstring吗
都不用,用while(networkstream.aataavailable){varcount=networkstream.read(buffer,0,buffer.Length);}
解决方案六:
引用4楼qqamoon的回复:
...都不用,用while(networkstream.aataavailable){varcount=networkstream.read(buffer,0,buffer.Length);}
这个选择不好,因为TCP协议本身从来没有支持过分包。while(networkstream.Available)可能导致读了半个xml,也可能导致读了两个xml。@walle_panpan如果是长连接,最好是和服务端协商一个更好的协议。比如先传一个长度,再传xml。你可以先收4个字节的长度,然后相应地收xml。或者,两个xml之间,用两个空行隔开,并保证xml之间不会出现两个空行。这样你可以ReadLine的时候,看到两个空行,进行割断。或者,你自己写一个状态机,来判断xml的起点和终点来进行割断(我认为正确实现相当不容易)。
解决方案七:
更正:并保证xml之间不会出现两个空行=〉并保证xml之中不会出现两个空行