Ich habe eine Anwendung, die ich für Windows 8/WinRT schreibe, die die StreamSocket-API verwendet, um eine Streaming-Verbindung zu einem Server zu tun. Das heißt, der Server überträgt Daten an den Client, manchmal mit Meta-Tags, und kann die Verbindung jederzeit trennen.Umgang mit WinRT StreamSocket trennt (Server- und Client-Seite)
Das Problem, das ich habe, ist, dass ich keine Ahnung habe, wie man erkennt, wenn der Server die Verbindung getrennt hat. Es scheint keine Ereignisse oder Eigenschaften in der StreamSocket-Klasse zu geben, weder in den Eingabe- oder Ausgabeströmen noch in den DataReader/DataWriter-Klassen, die irgendetwas mit dem Verbindungsstatus zu tun haben.
Darüber hinaus schlägt die DataReader-Methode ReadAsync nicht fehl, nachdem die Serverseite die Verbindung zum Client getrennt hat. Stattdessen ist die Operation erfolgreich, soweit ich das beurteilen kann, und die Daten, die sie in ihren Puffer füllt, sind nur das letzte, was der Server an sie geschickt hat (dh sie löscht nicht ihren internen Puffer, obwohl ich sehen kann, dass sie "verbraucht" hat) der Puffer bei jedem Aufruf von ReadByte). Dies geschieht für jeden weiteren Aufruf von ReadAsync - das Auffüllen des Puffers mit dem, was der Server zuletzt gesendet hat, bevor die Verbindung getrennt wurde. Hier ist eine vereinfachte Version des Codes:
public async Task TestSocketConnectionAsync()
{
var socket = new StreamSocket();
await socket.ConnectAsync(new HostName(Host), Port.ToString(),
SocketProtectionLevel.PlainSocket);
var dr = new DataReader(socket.InputStream);
dr.InputStreamOptions = InputStreamOptions.Partial;
this.cts = new CancellationTokenSource();
this.listenerOperation = StartListeningAsync(dr, cts);
}
public async Task StartListeningAsync(DataReader dr, CancellationTokenSource cts)
{
var token = cts.Token;
while (true)
{
token.ThrowIfCancellationRequested();
var readOperation = dr.LoadAsync(1024);
var result = await readOperation;
if (result <= 0 || readOperation.Status != Windows.Foundation.AsyncStatus.Completed)
{
cts.Cancel(); // never gets called, status is always Completed, result always > 0
}
else
{
while (dr.UnconsumedBufferLength > 0)
{
byte nextByte = dr.ReadByte();
// DriveStateMachine(nextByte);
}
}
}
}
Dies ist eine gute Information zu wissen.Vielen Dank. Es scheint, dass das DataReader.ReadAsync-Problem ein Fehler ist und es scheint, dass das entsprechende Team in Microsoft davon Kenntnis hat, also wird das hoffentlich behoben werden. In der Zwischenzeit habe ich Ihren Vorschlag, InputStream.ReadAsync auf meinem eigenen IBuffer (von WindowsRuntimeBuffer.Create) zu verwenden, versucht und es hat nicht nur funktioniert, sondern es scheint auch die Latenz um einen merklichen Betrag reduziert zu haben. –
hat dieses alte Posting gefunden. @ JeremyBell was ist der User-Voice-Bug, den du über 'InputStream.ReadAsync' geöffnet hast? Ist es jetzt gelöst? Ich habe auch seltsames Verhalten in meinem Input-Stream, dass es immer wieder Antworten vom Server sammelt, die nicht da sein sollten. Ich möchte alle Daten aus dem Socket lesen, bevor ich neue Daten an den Server sende. Siehe http://stackoverflow.com/questions/27533703/how-to-read-all-the-available-data-from-a-winrt-streamsocket-and-empty-the-input?noredirect=1#comment43496033_27533703 – philk