4 Stimmen

Tcp/Ip-Socket-Verbindungen in .NET

Für mein aktuelles Projekt muss ich XML-Daten über eine tcp/ip-Socket-Verbindung anfordern. Hierfür verwende ich die Klasse TcpClient:

Dim client As New TcpClient()
client.Connect(server, port)

Dim stream As NetworkStream = client.GetStream()
stream.Write(request)
stream.Read(buffer, 0, buffer.length)

// Output buffer and return results...

Bei kleinen Antworten funktioniert das wunderbar. Wenn ich jedoch anfange, größere Datenblöcke zu empfangen, scheint es, dass die Daten in Bursts über die Socket-Verbindung geschoben werden. Wenn dies geschieht, liest der stream.Read-Aufruf nur den ersten Burst, und so verpasse ich den Rest der Antwort.

Wie gehe ich am besten mit diesem Problem um? Zunächst habe ich versucht, nur Schleife, bis ich ein gültiges XML-Dokument hatte, aber ich fand, dass zwischen stream.Read Aufrufe der zugrunde liegende Stream manchmal heruntergefahren werden würde und ich würde auf den letzten Teil der Daten verpassen.

3voto

Sunny Milenov Punkte 21296

Sie erstellen eine Schleife zum Lesen.

Stream.Read gibt int für die bisher gelesenen Bytes zurück, oder 0, wenn das Ende des Streams erreicht ist.

Also, es ist wie:

int bytes_read = 0;
while (bytes_read < buffer.Length)
   bytes_read += stream.Read(buffer, bytes_read, buffer.length - bytes_read);

EDIT: Die Frage ist nun, wie Sie die Größe des Puffers bestimmen. Wenn Ihr Server zuerst die Größe sendet, ist das ok, Sie können das obige Snippet verwenden. Aber wenn Sie lesen müssen, bis der Server die Verbindung schließt, dann müssen Sie try/catch verwenden (was eine gute Idee ist, auch wenn Sie die Größe kennen), und verwenden Sie bytes_read zu bestimmen, was Sie erhalten haben.

int bytes_read = 0;
try
{
   int i = 0;
   while ( 0 < (i = stream.Read(buffer, bytes_read, buffer.Length - bytes_read) )
      bytes_read += i;
}
catch  (Exception e)
{
//recover
}
finally
{
if (stream != null)
   stream.Close();
}

2voto

Lou Franco Punkte 85315

Read ist keine Garantie dafür, dass der Stream vollständig gelesen wird. Es gibt die Anzahl der tatsächlich gelesenen Bytes zurück und 0, wenn es keine weiteren Bytes zu lesen gibt. Sie sollten die Schleife fortsetzen, um alle Daten aus dem Stream zu lesen.

0voto

Tute Punkte 6856

Dies ist ein möglicher Weg, dies zu tun und in "response" die Antwortzeichenfolge zu erhalten. Wenn Sie das Byte-Array benötigen, speichern Sie einfach ms.ToArray().

string response;

TcpClient client = new TcpClient();
client.Connect(server, port);
using (NetworkStream ns = c.GetStream())
using (MemoryStream ms = new MemoryStream())
{
    ns.Write(request);

    byte[] buffer = new byte[512];
    int bytes = 0;

    while(ns.DataAvailable)
    {
        bytes = ns.Read(buffer,0, buffer.Length);
        ms.Write(buffer, 0, bytes);
    }

    response = Encoding.ASCII.GetString(ms.ToArray());
}

0voto

pomarc Punkte 2184

Ich rate Ihnen dringend, WCF für solche Aufgaben zu nutzen. Es bietet nach einer nicht allzu steilen Lernkurve viele Vorteile gegenüber der reinen Socket-Kommunikation. Für die vorliegende Aufgabe stimme ich mit den vorangegangenen Antworten überein. Sie sollten eine Schleife verwenden und bei Bedarf dynamisch Speicher zuweisen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X