底层连接已关闭:连接意外关闭。数据太大了?

时间:2013-12-20 02:34:55

标签: c# wcf

我有一个服务器/客户端关系,客户端从服务器中提取ArrayList。如果我将服务器设置为始终发送一个空的ArrayList,那么我不会收到此错误。很明显,问题是我的数据对于连接来说太大了,而且在所有数据都可以通过之前它已经关闭了。

我已经调查了这个问题,并添加了这个问题/答案建议的功能: https://stackoverflow.com/a/285542/3036134许多解决方案都提出了相同的建议。

我相信我已经错误地实现了一些东西(我认为它很可能是服务行为MaxItemsInObjectGraph,因为我仍然得到同样的错误。但遗憾的是我无法弄清楚它有什么问题。这是我的代码:

我收到的错误:

CommunicationException was unhandled. The underlying connection was closed: The connection was closed unexpectedly.

我的WCF服务代码:

[ServiceContract]
public interface IModelData
{
    [OperationContract]
    ArrayList GetData();
}

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, MaxItemsInObjectGraph = 2147483647)]
public class ModelDataClient
{
    ChannelFactory<IModelData> HttpFactory;
    IModelData HttpProxy;

    public ModelDataClient()
    {
        HttpFactory = new ChannelFactory<IModelData>(
            new BasicHttpBinding(),
            new EndpointAddress("http://localhost:8000/ModelData"));

        HttpProxy = HttpFactory.CreateChannel();
    }

    public ArrayList GetData()
    {
        return HttpProxy.GetData();
    }
}

[ServiceBehavior(UseSynchronizationContext = false, InstanceContextMode = InstanceContextMode.Single, MaxItemsInObjectGraph = 2147483647)]
public class ModelDataServer : IModelData
{
    public delegate ArrayList GetData();
    public GetData _GetData { get; set; }

    public ModelDataServer()
    {
    }

    public ArrayList GetData()
    {
        return _GetData();
    }
}

我的客户端代码:

public partial class MainForm : Form
{  
    private ModelDataClient Client;

    public MainForm()
    {
        InitializeComponent();

        Client = new ModelDataClient();
    }

    private void Refresh()
    {
        ArrayList dataList = Client.GetData();
        // ********** ERROR POINTS TO LINE ABOVE!!!!!!!!!!!!!!!!!!!!

        // do something with datalist
    }
}   

我的服务器端代码:

public partial class ScraperForm : Form
{
    ServiceHost Host;
    ModelDataServer DataServer;

    ArrayList Data;

    public ScraperForm()
    {
        InitializeComponent();

        #region Start Data Server
        DataServer = new ModelDataServer();
        DataServer._GetData = new ModelDataServer.GetData(this.GetData);

        BasicHttpBinding bhttpb = new BasicHttpBinding();

        bhttpb.MaxBufferSize = 2147483647;
        bhttpb.MaxReceivedMessageSize = 2147483647;
        bhttpb.ReaderQuotas.MaxDepth = 32;
        bhttpb.ReaderQuotas.MaxStringContentLength = 8388608;
        bhttpb.ReaderQuotas.MaxArrayLength = 16384;
        bhttpb.ReaderQuotas.MaxBytesPerRead = 4096;
        bhttpb.ReaderQuotas.MaxNameTableCharCount = 16384;


        Host = new ServiceHost(DataServer, new Uri[]
            {
                new Uri("http://localhost:8000")
            });

        Host.AddServiceEndpoint(typeof(IModelData),
            bhttpb,
            "ModelData");

        Host.Open();

        Data = new ArrayList();
    }

    private void CloseSever()
    {
        Host.Close();
    }

    public void UpdateData() // Run on a timer
    {
        ArrayList Data = new ArrayList()

        // Update Data
    }

    public ArrayList GetData() // This is called by server which is called by client
    {
        return Data;           // no error if I return new ArrayList();
    }
}

编辑:问题是由于没有DataContract / DataMembers造成的?

更新 我使用本教程(以及相关的教程)从头开始重建了我的新实现:http://blogs.msdn.com/b/brunoterkaly/archive/2013/10/28/wcf-programming-how-to-write-a-client-app-that-connects-to-a-wcf-service.aspx(对于任何感兴趣的人)。

我没有使用ArrayList(大量拆箱)和Typed List(如果与WCF一起使用,而是作为数组出现),而是选择使用具有以下格式的字符串传递我的数据: “〜”表示列表中新成员的开头 “,”表示我的自定义数据类型之一的数据类型的结尾。 所以它可能看起来像“~NAME,1.29,1,4,123.1~NAME,1.23,3,1,13.2”等。我建议那些想要使用列表的人使用它。

我的新实现遇到了一个新问题,可能是相同/类似的问题。请参阅我的新问题:Object reference not set to an instance of an object - WCF Service and Delegates (WCF Hosted before Delegate is instantiated)

感谢大家的帮助。

1 个答案:

答案 0 :(得分:2)

您的客户端配置为什么?您已经显示了服务器端配置,但不要忘记客户端具有自己的配置设置。

查看服务器端配置,似乎在客户端上接收数据时发生了违规。

有关示例,请参阅here。您也可以通过编程方式执行此操作。

修改

现在我在评论中看到,您从服务器获取的ArrayList包含您自己的用户定义类型RFData。我现在相信这可能是你问题的根源。

数据合同描述了正在交换的数据。客户端和服务器之间使用数据协定来序列化和反序列化通过线路发送的数据。在定义要在WCF模型中使用的自己的类型时,需要使用数据合同/数据成员。基元以及许多内置的.NET类型已经有数据合约。

对于您的RFData类型,它将是这样的:

// Apply the DataContract to the type
[DataContract]
public class RFData
{
    // Apply the DataMemberAttribute to the various properties
    [DataMember]
    public double RFDouble { get; set; }
    [DataMember]
    public int RFInt { get; set; }
    [DataMember]
    public string RFString { get; set; }
}

我知道你有几个整数和双打,但你得到了要点。 Here是有关MSDN数据合同的真正有用的指南。