TcpClient的streamreader选择ReadLine还是ReadToEnd

问题描述

写一个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之中不会出现两个空行

时间: 2024-08-29 13:03:18

TcpClient的streamreader选择ReadLine还是ReadToEnd的相关文章

动态修改.Net StreamReader Encoding编码

stream|编码|动态 在.Net framework中StreamReader的使用encoding必须在构造器中指定,而且中途完全不可以更改. 在一般的情况下,这不会造成什么问题.一般若是从硬盘读取文件,单一文件内的编码一般都是统一的.即便是发现读错,亦可以关闭StreamReader,重启使用新的编码读取. 偏偏偶最近遇到了需要修改编码的需求,而且,我的程序没有关闭重读的机会.因为偶使用的StreamReader的BaseStream是一个Network Stream,我不可以关闭它--

C#编程总结(一)序列化总结_C#教程

序列化是将对象状态转换为可保持或传输的格式的过程.与序列化相对的是反序列化,它将流转换为对象.这两个过程结合起来,可以轻松地存储和传输数据. 几种序列化技术: 1)二进制序列化保持类型保真度,这对于在应用程序的不同调用之间保留对象的状态很有用.例如,通过将对象序列化到剪贴板,可在不同的应用程序之间共享对象.您可以将对象序列化到流.磁盘.内存和网络等等.远程处理使用序列化"通过值"在计算机或应用程序域之间传递对象. 2)XML 序列化仅序列化公共属性和字段,且不保持类型保真度.当您要提供

.NET中&amp;quot;延迟&amp;quot;特性的几个陷阱

.NET发展至今,其实各处都有"延迟(Lazy)"的痕迹,一个小小的"Laziness"给我们带来了不少灵活性1."延迟"的关键就在于"只在需要的时候处理数据",老赵曾经在多篇文章中提到了类似的概念,如<高阶函数.委托与匿名方法>及<您善于使用匿名函数吗?>.不过"延迟"本身也会给您带来一些陷阱,某些陷阱您很有可能也曾经遇到过.这篇文章便是总结了延迟特性的集中常见陷阱,并给出应对方案

ASP.NET 2.0高级控件之FileUpload控件

asp.net|高级|控件 应用程序中经常需要允许用户把文件上传到web服务器.尽管在ASP.NET 1.X也可以完成该功能,但在ASP.NET 2.0中使用FileUpload控件会更简单. 该控件让用户更容易地浏览和选择用于上传的文件,它包含一个浏览按钮和用于输入文件名的文本框.只要用户在文本框中输入了完全限定的文件名,无论是直接输入或通过浏览按钮选择,都可以调用FileUpload的SaveAs方法保存到磁盘上. 除了从WebControl类继承的标准成员,FileUpload控件还公开了

让你仔细看MSDN,你不看,现在又来问了:)

以下演练演示在安装期间如何使用自定义操作和 CustomActionData 属性创建数据库和数据库表.创建安装程序类 在"文件"菜单上指向"新建",然后选择"项目". 在"新建项目"对话框中,选择"项目类型"窗格中的"Visual Basic 项目",然后选择"模板"窗格中的"类库".在"名称"框中键入 DBCustomAct

序列化效率比拼——谁是最后的赢家Newtonsoft.Json

原文:序列化效率比拼--谁是最后的赢家Newtonsoft.Json       前言:作为开发人员,对象的序列化恐怕难以避免.楼主也是很早以前就接触过序列化,可是理解都不太深刻,对于用哪种方式去做序列化更是随波逐流--项目中原来用的什么方式照着用就好了.可是这么多年自己对于这东西还是挺模糊的,今天正好有时间,就将原来用过的几种方式总结了下,也算是做一个记录,顺便做了下性能测试.楼主算了下,从使用序列化到现在,用到的无非下面几种方式:(1)JavaScriptSerializer方式;(2)Da

C# Socket编程

一.同步方式:1.服务器端 server.cs using System; using System.Net.Sockets; using System.Net; using System.IO; class ProgServeur { static readonly ushort port = 50000; static void Main() { IPAddress ipAddress = new IPAddress( new byte[] { 127, 0, 0, 1 } ); TcpLi

Yale CAS + .net Client 实现 SSO(3)--实现 ASP.NET WebForm Client

原文地址: http://www.cnblogs.com/zhenyulu/archive/2013/01/22/2870936.html 第一部分:安装配置 Tomcat 第二部分:安装配置 CAS 第三部分:实现 ASP.NET WebForm Client 第四部分:实现基于数据库的身份验证 第五部分:扩展基于数据库的身份验证 第六部分:自定义登录页面 第三部分:实现 ASP.NET WebForm Client 1. 下载.NET CAS client. .NET CAS Client

很多时候我们都是缺少一个好的切入点(转)

  开发人员经常会碰到老板或上头安排的项目或需求,是自己完全陌生的领域,这个时候就会非常头痛,搜索引擎能解决大部分这些方面的问题,而有时因为自身问题或干脆找不到解决方案而非常抓狂......虽然干开发有10来年了,但还是会不时碰到这种问题,现做一下总结   前段时间老板出了一个难题给我,具体要求如下: 服务器上面有两张网卡分别连接电信和联通网络,要求软件在接到A请求时,使用电信网卡访问网络,接到B请求时,使用联通网卡访问网络,必须能多线程处理请求.还给了提示,说他听他朋友讲,使用路由功能就可以简