Ich habe ein paar Fragen ähnlich gesehen, aber bis jetzt habe ich keine wirkliche Lösung gesehen, die für die UWP-Plattform funktioniert.DataReader von SocketStream für UWP App
Ich verbinde mich mit einigen UPnP-Geräten im Netzwerk, die JSON zurück über Port 1255 senden. Ich habe die erste Verbindung funktioniert und die Sendeanforderung, die die Geräte anfordert, mir einige Informationen zu senden.
StreamSocket socket;
using (socket = new StreamSocket())
{
hostName = new HostName("192.168.0.nnn");
await socket.ConnectAsync(hostName, "1255");
//Code that does the request for info
await this.read();
}
public async Task<String> read()
{
string runStr = "";
uint inBufferCnt = 0;
using (reader = new DataReader(socket.InputStream))
{
reader.InputStreamOptions = Windows.Storage.Streams.InputStreamOptions.ReadAhead;
reader.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;
reader.ByteOrder = Windows.Storage.Streams.ByteOrder.LittleEndian;
inBufferCnt = await reader.LoadAsync(256); //InBuffer is always 256,
//even if there is more data waiting. If I put a task.delay in it will always return 256
while (reader.UnconsumedBufferLength > 0)
{
var iRead = reader.ReadString(reader.UnconsumedBufferLength);
runStr = runStr + iRead;
inBufferCnt = await reader.LoadAsync(64); //always hangs here.
//Even if I reduce to 1, it will sit waiting for new data
}
...
Alles funktioniert gut, bis zum letzten LoadAsync. Solange Daten im Stream vorhanden sind, werden sie, solange sie weniger als 64 Byte umfassen, um die While-Schleife herumgespielt. Wenn es weniger als dieses tho gibt, dann sitzt es einfach da und wartet auf mehr Daten. Also könnten 50 Bytes im Puffer liegen, die ich nicht bekommen kann. Im obigen Beispiel ist der inBufferCnt immer die genaue Größe des an LoadAsync übergebenen Wertes.
Ich habe verschiedene Dinge versucht, z. B. das Hinzufügen eines Timeouts, aber ich kann nicht auf irgendetwas zugreifen, nachdem die Ausnahme ausgelöst wurde, also weiß ich immer noch nicht, wie viele Daten im Stream sind.
CancellationTokenSource cts = new CancellationTokenSource();
cts.CancelAfter(5000);
...
inBufferCnt = await reader.LoadAsync(64).AsTask(cts.Token);
Ich habe keine Ahnung, wie viele Daten Ich werde von dem Gerät zurück, habe ich keinerlei Kontrolle über die Gerätekommunikation (andere als Info anfordern). Ich glaube, ich habe die Hälfte des Webs gelesen, während ich nach einer Lösung suche, aber ich kann nichts finden, was sich direkt auf dieses spezielle Problem bezieht.
Also lautet die Hauptfrage: "Wie soll man aus dem Socket-Stream lesen und dann, wenn es keine weiteren Daten gibt (zu diesem Zeitpunkt), einfach zurückgeben, was im aktuellen Stream sitzt in dem Puffer zu lesenden warten.
Hilfe ...
Vielen Dank für die Antwort, aber das Problem, das ich mit diesem Ansatz zu bekommen, ist, dass, wenn gab es Daten in dem Strom, aber nicht genug, um füllen Sie die gesamte sizeToReadEachTime, und wenn die Ausnahme auftritt, können Sie immer noch nicht auf die Daten zugreifen, ohne die Variable auf eine noch niedrigere Zahl zu verringern. Ich habe es geschafft, die Daten zu bekommen, indem ich den Wert auf 1 reduziere und dann die Daten mehr auswertet, dann kombiniert mit dem Ausnahme-Timeout weiß ich, dass ich alle Daten habe. Aber das scheint eine wirklich miese Art zu sein. IMO die von LoadAsync zurückgegebene uint sollte die Größe dessen zurückgeben, was tatsächlich im Puffer ist – MikeyTT
Sie sind willkommen :) Und ich weiß genau, was Ihr Problem ist. Also sagte ich, dass Sie ** Leseoption ** für den Eingabestream auf ** Teil ** am Anfang meiner Antwort setzen müssen. Auf diese Weise gibt die von LoadAsync zurückgegebene Uint die Größe dessen zurück, was sich tatsächlich im Puffer befindet, selbst wenn Daten im Stream vorhanden waren, aber nicht genug, um die gesamte sizeToReadEachTime zu füllen. Alle Daten werden abgerufen, bevor die Ausnahme auftritt. Die Ausnahme tritt nur auf, wenn keine Daten im Stream vorhanden sind. Sie müssen also den Wert nicht auf eine noch niedrigere Zahl oder auf 1 in meiner obigen Lösung reduzieren. –
Ich hatte ursprünglich die Partial-Option verwendet, und ich denke, ich habe den Großteil des Code-Snippets von hier: http://donatas.xyz/streamsocket-tcpip-client.html. Aber ich habe festgestellt, dass die Uint immer die Größe des Wertes hat, den du an ihn übergibst, und er hing immer an der LoadAsync, wenn weniger Daten zur Verfügung standen. Ich werde es später in der Woche nochmal versuchen, wenn ich wieder an meinem Dev-Arbeitsplatz bin. Ich glaube nicht, dass ich die Absage auch teilweise versucht habe, also werde ich mich ärgern, wenn das klappt;) – MikeyTT