我们最近更改了硬件配置,并开始在通过我们的 Web 服务发送大文件时遇到问题。在随机情况下,我们发送的肥皂消息在接收端会损坏。收到的消息内容与发送的消息内容不同。我写了一个小测试程序,它能够小规模地重现我们的问题。
该程序在接收端有一个 WCF Web 服务,在发送端有一个 Windows 窗体应用程序。表单应用程序将一个大字符串发送到 WCF Web 服务。两者都使用 wshttpbinding 进行通信。WCF Web 服务安装在 Windows Server 2008 R2 x64 上的 IIS7 上。Windows 窗体应用程序在使用 VMWare (5.0) 虚拟化的 Windows Server 2012 标准版上运行。
尝试读取 xml 时抛出的异常总是如下(XML 损坏):
System.Xml.XmlException: 'B' is an unexpected token. Expecting white space. Line 1, position 5820605.
at System.Xml.XmlTextReaderImpl.Throw(String res, String arg)
at System.Xml.XmlTextReaderImpl.ParseAttributes()
at System.Xml.XmlTextReaderImpl.ParseElement()
at System.Xml.XmlTextReaderImpl.ParseElementContent()
at System.Xml.XmlLoader.LoadNode(Boolean skipOverWhitespace)
at System.Xml.XmlLoader.LoadDocSequence(XmlDocument parentDoc)
at System.Xml.XmlDocument.Load(XmlReader reader)
at System.Xml.XmlDocument.LoadXml(String xml)
at WCFReciever.Service1.SendXml(String xml) in c:\xxxxxxx\visual studio 2010\Projects\WCFReciever\WCFReciever\Service1.svc.cs:line 22
笔记
- 当我们在不同的服务器(windows server 2008 R2 x64,物理安装)上运行 windows 窗体应用程序时,问题不再出现。由于损坏是随机的,我们排除了任何配置、绑定、请求限制问题。
- basicHttpbinding 显示同样的问题
- 该软件已运行无问题 3 年
- 不同的内容会出现问题( byte[] +/- 10 MB、string > 10MB、XML 45 MB 等)
- 我们已经调试这个问题好几天了,没有任何结果
提前致谢!
测试程序的代码片段
表格申请
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
try
{
Result.Text = string.Empty;
var client = new WCFReciever.Service1Client();
//some large file, in this case a xml structured file, 44MB
var osil = File.ReadAllText("test.osil");
if (client.SendXml(osil))
{
Result.Text += "success";
}
else
{
Result.Text += "failed";
}
}
catch (Exception ex)
{
Result.Text += ex.ToString();
}
}
}
}
WCF 接收器
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Xml;
using System.IO;
namespace WCFReciever
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
public class Service1 : IService1
{
public bool SendXml(string xml)
{
try
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
return true;
}
catch (Exception e)
{
return false;
}
}
}
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
[ServiceContract]
public interface IService1
{
[OperationContract]
bool SendXml(string xml);
}
}
绑定配置
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<bindings>
<wsHttpBinding>
<binding name="wsHttpBinding1" closeTimeout="00:10:00"
openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"
messageEncoding="Text" textEncoding="utf-8"
useDefaultWebProxy="true">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647"
maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="WCFReciever.Service1">
<endpoint contract="WCFReciever.IService1" binding="wsHttpBinding" bindingConfiguration="wsHttpBinding1"/>
</service>
</services>
</system.serviceModel>