Laden...

(WCF) NetTcpBinding: Problem mit Nachrichtengröße

Erstellt von DonC vor 13 Jahren Letzter Beitrag vor 13 Jahren 4.488 Views
D
DonC Themenstarter:in
30 Beiträge seit 2007
vor 13 Jahren
(WCF) NetTcpBinding: Problem mit Nachrichtengröße

Hi Leutz,

ich habe ein Problem mit der Nachrichtengröße meiner Client-Server-Anwendung.
Über eine Callback-Methode versende ich String-Arrays vom Server zu den einzelnen Clients.

Wenn ich ein String-Array mit 20.000 Einträgen versenden möchte, klappt das ohne Probleme. Sobald das Array jedoch beispielsweise 200.000 Einträge hat, wird es nicht mehr übertragen. Kurioserweise bekomme ich auch keinerlei Exception ausgegeben. Es passiert einfach nichts und der Callback wird auch nicht auf dem Client ausgelöst. Ich verwende ein NetTcpBinding zur Übertragung zwischen Server und Client und habe bereits die Einstellungen MaxReceivedMessageSize, MaxBufferSize, MaxBufferSize und MaxBufferPoolSize ausprobiert, indem ich alle auf einen Wert von 524288000 gesetzt habe (beim Server als auch beim Client), was ungefähr einer Stream-Größe von 200 MB entsprechen sollte.

Gebracht hat das leider nichts. Bin gerade etwas ratlos. Vielleicht hat ja jemand von Euch eine Idee?

Gruß,
Chris

742 Beiträge seit 2005
vor 13 Jahren

Ich finde das schon ziemlich krass, überhaupt 200.000 Einträge abzufragen. Natürlich kann man 200.000 Einträge wollen, weil man sie bearbeiten muss, aber dann sollte man das asynchron machen und nicht mit einer Riesigen Response, die alles blockiert.

Ich würde das Konzept überdenken und mir die Arbeit ersparen in diese Richtung nach Lösungen zu suchen.

J
1.114 Beiträge seit 2007
vor 13 Jahren

Schliess mich malignate's Meinung an. Meide zu lange Responsezeiten in Callbackverträgen. Bedenke, dass der Server die Info all seinen, wieviel auch immer, in der Regel einem nach dem anderen die Info zusendet. Besser ist, die Clients lediglich zu benachrichtigen, dass er sich bitte selbst was Neues vom Server holen soll. Hier ist zwar grundsätzlich das gleiche Problem (sofern nicht bewusst der WCF so konfiguriert wird, dass er seine Clients asynchron bedienen soll), aber so kannst du dir leicht überlegen, dass der Client die Infos jeweils häpchenweise abfragt (z.B. in 1000er Blöcken)

S
8.746 Beiträge seit 2005
vor 13 Jahren

Da gibt es noch MaxArraySize und MaxStringContentLength. Darüberhinaus kann dein Problem auch beim Webserver liegen. Da i.d.R. eingehende Requests komplett gecached werden, ist die maximale Größe des Requests beschränkt. Default im IIS sind 4 MB.

D
DonC Themenstarter:in
30 Beiträge seit 2007
vor 13 Jahren

Also ich habe den Server direkt als App und nicht im IIS aufgesetzt. Wo genau kann ich denn die MaxArraySize einstellen? Ich arbeite ürbigens nicht mit Config-Dateien, sondern codiere das direkt.

Der Aufruf meine Methode, welche das Array zurückgibt, erfolgt übrigens schon asynchron. Im Detail läuft das so ab:

  1. Client "sagt" dem Server über eine Methode (ohne Rückgabewert), er möchte das Datenarray erhalten

  2. Server startet eine asynchrone Methode, in der er die Daten für das Array ermittelt

  3. Server hat Daten gesammelt und ruft beim Client eine Callback-Methode auf, bei der er als Parameter das gefüllte Array übergibt. Und genau hier liegt das Problem, da das Array offenbar zu groß ist.

D
DonC Themenstarter:in
30 Beiträge seit 2007
vor 13 Jahren

Also ich habe MaxArrayLength und MaxStringContentLength auf 1GB gesetzt und trotzdem dasselbe Problem wie vorher 😦

D
DonC Themenstarter:in
30 Beiträge seit 2007
vor 13 Jahren

Habe übrigens noch ein interessantes Detail rausgefunden. Ich kann bei meiner Client-Server-Anwendung string-Arrays mit max. 65535 Elementen übertragen. Sobald das Array 65536 Elemente oder mehr aufweist, geht nix mehr durch. Nun weist die "MaxReceivedMessageSize"-Eigenschaft ja einen Default-Wert von genau 65536 Bytes auf. Daher dachte ich, dass es eventuell ja daran liegen könnte, nur hat eine Erhöhung des Wertes nichts gebracht. Im folgenden liste ich den Code von Server und Client zur Initialisierung der Kommunikationskanäle auf. Vielleicht fällt ja jemandem von Euch was dazu ein.

Code auf Serverseite:


rateServer = new CServer();

                ServiceHost serverHost =
                    new ServiceHost(rateServer);

                NetTcpBinding binding =
                    new NetTcpBinding(SecurityMode.None, true);
                Uri address =
                    new Uri(@endpoint_adress);

                int value = 2147483647;

                XmlDictionaryReaderQuotas rq = new XmlDictionaryReaderQuotas();
                rq.MaxArrayLength = value;
                rq.MaxStringContentLength = value;
                rq.MaxBytesPerRead = value;

                binding.ReaderQuotas = rq;
                binding.MaxBufferPoolSize = value;
                binding.MaxBufferSize = value;
                binding.MaxReceivedMessageSize = value;
                
                serverHost.AddServiceEndpoint(
                    typeof(IRateService), binding, address);

                serverHost.Open();

Code auf Clientseite:


System.ServiceModel.Channels.Binding binding =
                new NetTcpBinding(SecurityMode.None, true);
                EndpointAddress address =
                    new EndpointAddress(@endpoint_adress);

                int value = 2147483647;

                XmlDictionaryReaderQuotas rq = new XmlDictionaryReaderQuotas();
                rq.MaxArrayLength = value;
                rq.MaxStringContentLength = value;
                rq.MaxBytesPerRead = value;

                ((NetTcpBinding)binding).ReaderQuotas = rq;
                ((NetTcpBinding)binding).MaxReceivedMessageSize = value;
                ((NetTcpBinding)binding).MaxBufferSize = value;
                ((NetTcpBinding)binding).MaxBufferPoolSize = value;                

                InstanceContext context = new InstanceContext(this);

                DuplexChannelFactory<IRateService> factory =
                    new DuplexChannelFactory<IRateService>
                    (context, binding, address);
                
                proxy = factory.CreateChannel();

A
350 Beiträge seit 2010
vor 13 Jahren

Ich finde es seeeeeehr ungünstig Arrays dieser Größe übers Netz zu jagen.

Denk mal lieber über Stückelung oder Streams nach bzw. Asynchrone Methoden.
Das was du vor hast ist eifnach zu viel für den Äther .

Grüße