2013-12-20 3 views
2

У меня есть отношения между сервером и клиентом, когда клиент вытаскивает 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 
    } 
} 

My Server Side Код:

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(); 
    } 
} 

EDIT: ли проблема быть, вызвана не имея DataContract/DataMembers?

UPDATE Я перестроил свою новую реализацию с нуля с помощью этого учебника (и связанных с них): 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 (много распаковки) и типизированного списка (выводится как массив, если используется с 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

Я считаю, что сервер * и клиент * имеют ограничения. –

+2

Yuck! Почему 'ArrayList'? Вам действительно нужна коллекция произвольных предметов? –

+0

@ ta.speot.is да, я считаю, что приведенный выше код устанавливает пределы. Как вы думаете, я отправляю слишком много данных для того, что я здесь установил? Я считаю, что они установлены на максимум – janderson

ответ

2

Какова ваша клиентская сторона настроена как? Вы указали конфигурацию на стороне сервера, но не забывайте, что клиентская сторона имеет собственные настройки конфигурации.

Ознакомившись с вашей конфигурацией на стороне сервера, похоже, что нарушение происходит при приеме данных на клиенте.

См. Пример here. Вы также можете сделать это программно.

Редактировать

Теперь я вижу в комментариях, что это ArrayList вы получаете от сервера содержит свой собственный пользовательский тип RFData. Теперь я считаю, что это, вероятно, источник вашей проблемы.

Данные Контракты описывают данные, которые обмениваются. Контракты данных используются между Клиентом и Сервером для сериализации и де-сериализации данных, которые отправляются по кабелю. Вам необходимо использовать Data Contracts/Data Members, когда вы определяете свой собственный тип, который будет использоваться в модели WCF. Примитивы, а также многие из встроенных типов .NET уже имеют Data Contracts.

Для вашего 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.

+0

Привет, Дерек, спасибо за вашу помощь. У меня нет файла app.config в моем проекте. Есть ли другой способ получить этот файл конфигурации? – janderson

+0

@Watson, вы должны четко указать, каков ваш тип проекта клиент/сервер. 'app.config' доступен только в некоторых проектах. Для других проектов вы должны увидеть 'web.config' или' servicereferences.clientconfig'. Если проект вашего клиента представляет собой проект WinForms, вы можете создать 'app.config', если он еще не находится в проекте. –

+0

Спасибо за помощь Дерек, я очень ценю это. Пожалуйста, см. Мое «Обновление» в нижней части моего сообщения. – janderson

Смежные вопросы