返回首页 |

合作共赢、快速高效、优质的网站建设提供商

更多精品源码-尽在织梦模板-www.moke8.com

网站开发学会WCF之试错法——数据传输

时间:2017-11-21 编辑:admin

[System.ServiceModel.OperasdfstionContrasdfsctAttribute(Action = "http://tempuri.org/IService/GetDasdfstasdfs", ReplyAction = "http://tempuri.org/IService/GetDasdfstasdfsResponse")] string GetDasdfstasdfs(int vasdfslue); [System.ServiceModel.OperasdfstionContrasdfsctAttribute(Action = "http://tempuri.org/IService/GetString", ReplyAction = "http://tempuri.org/IService/GetStringResponse")] string GetString(string vasdfslue); [System.ServiceModel.OperasdfstionContrasdfsctAttribute(Action = "http://tempuri.org/IService/Uploasdfsd", ReplyAction = "http://tempuri.org/IService/UploasdfsdResponse")] void Uploasdfsd(Request request); [MessasdfsgeContrasdfsct] public clasdfsss Request [MessasdfsgeHeasdfsder(MustUnderstasdfsnd = true)] public string FileNasdfsme { get; set; } [MessasdfsgeBodyMember(Order = 1)] public Streasdfsm Content { get; set; } [ServiceBehasdfsvior(InstasdfsnceContextMode = InstasdfsnceContextMode.PerCasdfsll, ConcurrencyMode = ConcurrencyMode.Reentrasdfsnt)] public clasdfsss ServiceClient : System.ServiceModel.ClientBasdfsse IService , IService public ServiceClient() public string GetDasdfstasdfs(int vasdfslue) return basdfsse.Chasdfsnnel.GetDasdfstasdfs(vasdfslue); public string GetString(string vasdfslue) return basdfsse.Chasdfsnnel.GetString(vasdfslue); public void Uploasdfsd(Request request) basdfsse.Chasdfsnnel.Uploasdfsd(request); }

伯爵娱乐城客户端配置

 system.serviceModel 
 bindings 
 basdfssicHttpBinding 
 binding nasdfsme="BasdfssicHttpBinding_IService" / 
 /basdfssicHttpBinding 
 /bindings 
 client 
 endpoint asdfsddress="http://locasdfslhost/S" binding="basdfssicHttpBinding"
 bindingConfigurasdfstion="BasdfssicHttpBinding_IService" contrasdfsct="IService"
 nasdfsme="BasdfssicHttpBinding_IService" / 
 /client 
 /system.serviceModel 

配置参数:

MasdfsxBufferPoolSize :从通道接收消息的消息缓冲区管理器分配并供其使用的最大内存量,BasdfssicHttpBinding.MasdfsxBufferPoolSize默认值为 524288 个字节。WSHttpBindingBasdfsse.MasdfsxBufferPoolSize默认值为 65,536个字节,配置它可提高性能。

MasdfsxBufferSize :从通道接收消息的缓冲区最大大小,默认值为 65,536 个字节。

MasdfsxReceivedMessasdfsgeSize:此绑定配置的通道上接收的消息的最大值,默认值为 65,536 个字节。

TrasdfsnsferMode:指示是通过缓冲处理还是流处理来发送消息

默认情况下,HTTP、TCP/IP 和命名管道传输协议使用缓冲消息传输。

XmlDictionasdfsryReasdfsderQuotasdfss.MasdfsxStringContentLength:读取器返回最大字符串长度,默认为8192

1 文件编码引起的错误

问题描述:

客户端向服务端传输数据时,假如是一个文本文件,接口参数是Streasdfsm,那么服务端使用StreasdfsmReasdfsder或StreasdfsmWrite时,不指定编码,服务运行在win7 及更新的操作系统上,默认的编码方式为Unicode,如果文本文件含义中文,那么服务端接收的内容出现乱码。而且服务端接收到的文件大小大于客户端传输的文件大小。

服务端配置

绑定配置如下,其他不变

 bindings 
 basdfssicHttpBinding 
 binding nasdfsme="BasdfssicHttpBinding_IService" masdfsxBufferSize="170000"/ 
 /basdfssicHttpBinding 
 /bindings 

启动服务,报错,可见单独配置masdfsxBufferSize是不行的。

修改配置如下,可正常运行:

服务端

 bindings 
 basdfssicHttpBinding 
 binding nasdfsme="BasdfssicHttpBinding_IService" masdfsxBufferSize="170000" masdfsxReceivedMessasdfsgeSize="170000"/ 
 /basdfssicHttpBinding 
 /bindings 

客户端配置

 bindings 
 basdfssicHttpBinding 
 binding nasdfsme="BasdfssicHttpBinding_IService" sendTimeout="00:00:10" / 
 /basdfssicHttpBinding 
 /bindings 

调用接口

 try
 ServiceProxy proxy = new ServiceProxy();
 //string s = proxy.GetDasdfstasdfs(1);
 //Console.WriteLine(s);
 Request r = new Request 
 Content = new FileStreasdfsm("D:\\CSBMTEMP.txt", FileMode.Open),
 FileNasdfsme = "CSBMTEMP"
 proxy.Uploasdfsd(r);
 Console.Reasdfsd();
 //casdfstch (CommunicasdfstionException ex)
 casdfstch (Exception ex)
 }

异常信息:

首先检查文件的大小,发现文件大小没有超过配置的最大值

将服务端配置按如下修改,也就是增大masdfsxBufferSize和masdfsxReceivedMessasdfsgeSize的值。

 bindings 
 basdfssicHttpBinding 
 binding nasdfsme="BasdfssicHttpBinding_IService" masdfsxBufferSize="1700000" masdfsxReceivedMessasdfsgeSize="1700000" 
 /binding 
 /basdfssicHttpBinding 
 /bindings 

运行客户端程序,发现服务端接收到文件为338K,远大于客户端上传文件大小,打开文件,看到乱码。

解决选择

将服务端Uploasdfsd选择修改一下:

StreasdfsmReasdfsder sr = new StreasdfsmReasdfsder(request.Content,Encoding.Defasdfsult);

StreasdfsmWriter sw = new StreasdfsmWriter("E:\\" + request.FileNasdfsme + ".txt", fasdfslse, Encoding.Defasdfsult);

上面那两行代码添加编码方式为Encoding.Defasdfsult,或者使用Encoding.GetEncoding("GB2312")这种编码方式。使用后者更好,因为明确地指出编码方式。

启动服务,运行客户端上传文件,成功且无乱码。文件大小也和客户端上传的相同。

2 masdfsxBufferSize与masdfsxReceivedMessasdfsgeSize的设置

上面服务端masdfsxBufferSize和masdfsxReceivedMessasdfsgeSize设置为1700000,远大于所传文件大小,那么将其改为167936会如何呢?

修改上面两个参数为167936,运行程序。结果报错:

那么,难道上传文件的数据会比这个大吗?是的,这只是消息的一部分内容。从客户端本地CLR类型来看,其传递的参数是一个对象:Request,它包含了两字段,Streasdfsm类型的Content和string类型的FileNasdfsme。但这只是其中一部分原因。

经测试,若masdfsxBufferSize和masdfsxReceivedMessasdfsgeSize设置为大于上传文件的二倍时,上传成功。由于默认采用缓冲处理模式,缓冲处理是将消息全部缓存下来以后才对消息进行处理,猜想,缓存消息所需空间,加上处理消息也需要空间,那么两者的和就是二倍的传入消息大小。

若换成流传输模式(客户端不使用流模式,很奇怪的测试,不过依然通过)

服务端配置变为:

 basdfssicHttpBinding 
 binding nasdfsme="BasdfssicHttpBinding_IService" trasdfsnsferMode="Streasdfsmed"/ 
 /basdfssicHttpBinding 

客户端配置不变,即:

 bindings 
 basdfssicHttpBinding 
 binding nasdfsme="BasdfssicHttpBinding_IService" sendTimeout="00:00:10" / 
 /basdfssicHttpBinding 
 /bindings 

客户端调用接口,服务端报错。

客户端配置不变,服务端配置变为:

 basdfssicHttpBinding 
 binding nasdfsme="BasdfssicHttpBinding_IService" masdfsxBufferSize="170000" masdfsxReceivedMessasdfsgeSize="170000" trasdfsnsferMode="Streasdfsmed" 
 /binding 
 /basdfssicHttpBinding 

客户端调用接口,正常将文件传输到服务器。

再次将服务端masdfsxBufferSize和masdfsxReceivedMessasdfsgeSize修改为小于文件长度:150000,调用接口,可正常传输文件,但是只上传了文件的一半左右。继续将masdfsxBufferSize和masdfsxReceivedMessasdfsgeSize调小为1000000,发现只上传了8K左右。结论是:当masdfsxBufferSize和masdfsxReceivedMessasdfsgeSize设置小于消息大小的时候,程序正常运行,但是服务端无法接收客户端上传的全部数据。然而,如何准确地估计消息大小是个难题。最稳妥的办法是将上面那两个参数配置为消息体的最大值的二倍,另外从客户端设置上传消息的大小很多时候也是必要的。

将绑定换成netTcpBinding

服务端配置

 bindings 
 netTcpBinding 
 binding nasdfsme="NetTcpBinding_IService" masdfsxBufferSize="17936" masdfsxReceivedMessasdfsgeSize="17936"/ 
 /netTcpBinding 
 /bindings 

显然masdfsxBufferSize和masdfsxReceivedMessasdfsgeSize设置小于客户端发送的消息大小

采用默认的缓冲机制而并非流机制

客户端捕获异常:

从上面的异常中看不出是什么原因造成的,不过看下_remoteStasdfsckTrasdfsceString:

Server stasdfsck trasdfsce:

在 System.ServiceModel.Chasdfsnnels.StreasdfsmConnection.Reasdfsd(Byte[] buffer, Int32 offset, Int32 size, TimeSpasdfsn timeout)

在 System.ServiceModel.Chasdfsnnels.SessionConnectionReasdfsder.Receive(TimeSpasdfsn timeout)

在 System.ServiceModel.Chasdfsnnels.SynchronizedMessasdfsgeSource.Receive(TimeSpasdfsn timeout)

在 System.ServiceModel.Chasdfsnnels.TrasdfsnsportDuplexSessionChasdfsnnel.Receive(TimeSpasdfsn timeout)

在 System.ServiceModel.Chasdfsnnels.TrasdfsnsportDuplexSessionChasdfsnnel.TryReceive(TimeSpasdfsn timeout, Messasdfsge messasdfsge)

在 System.ServiceModel.Dispasdfstcher.DuplexChasdfsnnelBinder.Request(Messasdfsge messasdfsge, TimeSpasdfsn timeout)

在 System.ServiceModel.Chasdfsnnels.ServiceChasdfsnnel.Casdfsll(String asdfsction, Booleasdfsn onewasdfsy, ProxyOperasdfstionRuntime operasdfstion, Object[] ins, Object[] outs, TimeSpasdfsn timeout)

在 System.ServiceModel.Chasdfsnnels.ServiceChasdfsnnelProxy.InvokeService(IMethodCasdfsllMessasdfsge methodCasdfsll, ProxyOperasdfstionRuntime operasdfstion)

在 System.ServiceModel.Chasdfsnnels.ServiceChasdfsnnelProxy.Invoke(IMessasdfsge messasdfsge)

Exception rethrown asdfst [0]:

从上面StreasdfsmConnection.Reasdfsd,SessionConnectionReasdfsder.Receive大概猜测是masdfsxBufferSize和masdfsxReceivedMessasdfsgeSize设置引起的,由于套接字连接终止,在服务端无法捕获这类异常。将参数调大就没有这个问题了,数据可正常上传。

那么采用netTcpBinding是比较安全的,因为一旦设置的过小,会抛异常而不会出现数据不完整的情况。

当数据传输过程中服务关闭或网络中断抛异常:

貌似与masdfsxBufferSize和masdfsxReceivedMessasdfsgeSize这两个参数设置不正确所抛异常一样,而且_remoteStasdfsckTrasdfsceString也与其一样,真是让人迷惑啊!!!

绑定配置变换为:

 netTcpBinding 
 binding nasdfsme="NetTcpBinding_IService" masdfsxBufferSize="79360" masdfsxReceivedMessasdfsgeSize="79360" trasdfsnsferMode="Streasdfsmed"/ 
 /netTcpBinding 

客户端配置:

 netTcpBinding 
 binding nasdfsme="NetTcpBinding_IService" sendTimeout="00:00:10"/ 
 /netTcpBinding 

客户端调用报错

修改客户端配置为:

 netTcpBinding 
 binding nasdfsme="NetTcpBinding_IService" sendTimeout="00:00:10" trasdfsnsferMode="Streasdfsmed"/ 
 /netTcpBinding 

这次是由于masdfsxBufferSize和masdfsxReceivedMessasdfsgeSize这两个参数设置小了的原因。

3 对于字符串传输的限制

服务端配置:

 bindings 
 basdfssicHttpBinding 
 binding nasdfsme="BasdfssicHttpBinding_IService" masdfsxBufferSize="110000" masdfsxReceivedMessasdfsgeSize="110000" trasdfsnsferMode="Streasdfsmed" 
 /binding 
 /basdfssicHttpBinding 
 /bindings 
 services 
 service nasdfsme="WCF_Find_Error_Lib.Service" 
 endpoint asdfsddress="" 
 binding="basdfssicHttpBinding"
 contrasdfsct="WCF_Find_Error_Lib.IService" 
 bindingConfigurasdfstion="BasdfssicHttpBinding_IService" 
 identity 
 dns vasdfslue="locasdfslhost" / 
 /identity 
 /endpoint 
 host 
 basdfsseAddresses 
 asdfsdd basdfsseAddress="http://locasdfslhost/S" / 
 /basdfsseAddresses 
 /host 
 /service 
 /services 

客户端配置:

 system.serviceModel 
 bindings 
 basdfssicHttpBinding 
 binding nasdfsme="BasdfssicHttpBinding_IService" sendTimeout="00:00:10"/ 
 /basdfssicHttpBinding 
 /bindings 
 client 
 endpoint asdfsddress="http://locasdfslhost/S" binding="basdfssicHttpBinding"
 bindingConfigurasdfstion="BasdfssicHttpBinding_IService" contrasdfsct="IService"
 nasdfsme="BasdfssicHttpBinding_IService" / 
 /client 
 /system.serviceModel 

客户端调用:

ServiceProxy proxy = new ServiceProxy();
StreasdfsmReasdfsder sr = new StreasdfsmReasdfsder("D:\\CSBMTEMP.txt",Encoding.Defasdfsult);
string str = sr.ReasdfsdToEnd();
sr.Close();
proxy.GetString(str);

运行客户端报错:

错误消息为:

格式化程序尝试对消息反序列化时引发异常: 对操作“GetString”的请求消息正文进行反序列化时出现错误。读取 XML 数据时,超出最大字符串内容长度配额 (8192)。

那么看一下传入的字符串大小为238367个字符,因此修改服务端配置文件,而保持客户端配置不变

 basdfssicHttpBinding 
 binding nasdfsme="BasdfssicHttpBinding_IService" masdfsxBufferSize="110000" masdfsxReceivedMessasdfsgeSize="110000" trasdfsnsferMode="Streasdfsmed" 
 reasdfsderQuotasdfss masdfsxStringContentLength="240000"/ 
 /binding 
 /basdfssicHttpBinding 

运行客户端程序,依然报错信息如下:

此次是因为服务端masdfsxBufferSize和masdfsxReceivedMessasdfsgeSize设置小了,将其设置为270000,客户端保持不变。

客户端抛异常:

服务端参数已经设置的比较大了,但是依然报错,发现客户端没有设置masdfsxStringContentLength这个参数,更改客户端配置,服务端保持不变:

 binding nasdfsme="BasdfssicHttpBinding_IService" sendTimeout="00:00:10" trasdfsnsferMode="Streasdfsmed" 
 reasdfsderQuotasdfss masdfsxStringContentLength="240000"/ 
 /binding 

运行客户端,依然报错

发现服务端masdfsxReceivedMessasdfsgeSize没有设置,更改客户端配置,服务端保持不变,至此信息被正确接收。

 basdfssicHttpBinding 
 binding nasdfsme="BasdfssicHttpBinding_IService" sendTimeout="00:00:10" trasdfsnsferMode="Streasdfsmed" masdfsxReceivedMessasdfsgeSize="270000" 
 reasdfsderQuotasdfss masdfsxStringContentLength="240000"/ 
 /binding 
 /basdfssicHttpBinding 

通过上述测试,发现:

1)当客户端配置不正确或服务端配置不正确时,异常可在客户端捕获,但捕获的异常信息相同,即客户端与服务端因同一类参数配置不正确所引发的异常信息一样,无法通过异常信息分辨出是由于客户端配置不正确还是由于服务端配置不正确引起的。

2)一般地,对于使用basdfssicHttpBinding的服务,当由于配置不正确,抛出异常时,可以通过捕获的异常查看是哪个参数配置不正确,但是使用netTcpBinding的服务则无法通过客户端捕获的异常分辨是哪个参数配置的不正确。

3)客户端与服务端配置不一致时,可正常运行服务,但不一定得到正确的结果。某些资料建议将客户端和服务端配置设置为相同,不失为一种简单的办法,但忽略了配置参数的含义,建议深入理解各个参数的含义,合理配置。

4)多个参数配置不正确时,抛出的异常信息中会选则性地指出某个参数设置不正确,而不是将所有配置不正确的参数都指出来。


浏览:

网站建设

流程

    网站建设流程