Hallo zusammen,
ich sitze jetzt schon das ganze Wochenende an einem Problem und ich komme einfach nicht darauf. Ich hoffe einer von euch kann mir helfen.
Ich lese Daten aus einem Networkstream und füge sie dann einer List<byte> hinzu, dass sieh so aus: (TcpClient)
public void ReceiveData()
{
_serverStream = _clientSocket.GetStream();
_serverStream.ReadTimeout = 100;
byte[] bytes = new byte[128];
List<byte> allBytes = new List<byte>();
while (true)
{
if (_serverStream.DataAvailable)
{
int i = 0;
do
{
try
{
i = _serverStream.Read(bytes, 0, bytes.Length);
allBytes.AddRange(bytes.Take(i));
}
catch (Exception e)
{
MessageBox.Show(e.Message + " " + i);
}
} while (i > 0);
}
else
{
break;
}
}
OnMessageRecieved(new MessageRecievedEventArgs(allBytes.ToArray()));
allBytes.Clear();
}
Leider komme ich nie aus der inneren Schleife raus und bekomme eine IOException geworfen (Von der Übertragungsverbindung usw....).
i wird aus irgendeinem Grund nie 0.
Nun das schreiben vom Server aus.
public static void GetDrives(TcpClient client)
{
NetworkStream networkStream = client.GetStream();
byte[] bytesOption = Encoding.ASCII.GetBytes("A");
networkStream.Write(bytesOption, 0, bytesOption.Length);
DriveInfo[] allDrives = DriveInfo.GetDrives();
foreach (DriveInfo d in allDrives)
{
if (d.IsReady)
{
byte[] bytes = Encoding.ASCII.GetBytes(d.RootDirectory + " " + d.VolumeLabel + " " + d.DriveFormat + " " + d.TotalSize / 1024 / 1024 + " ~ ");
networkStream.Write(bytes, 0, bytes.Length);
}
}
networkStream.Flush();
}
ich schreibe hier zu Testzwecken einfach meine Laufwerke zurück.
Sieht jemand meinen Fehler? Lege ich den Try Catch Block außerhalb von der Schleife, sodass rausgesprungen wird bei einer Exception funktioniert alles und alle Daten finden ihren Weg.
Danke euch 😃
Edit:
byte[] bytesOption = Encoding.ASCII.GetBytes("A");
networkStream.Write(bytesOption, 0, bytesOption.Length);
Ich schreibe übrigens erst ein A in den Stream, damit der Client weiß wie er damit umgehen soll.
Quasi als Kommando.
Die Begründung der IOException und die korrekte Implementierung des Lesens eines Network Streams findest Du im ersten Google Treffer bei der Suche nach "c# read from network stream" unter: What is the correct way to read from NetworkStream in .NET
if the ReceiveTimeout is reached an IOException will be raised...
with an InnerException of type SocketException and ErrorCode 10060
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Ich habe natürlich gegoogelt bevor ich hier um helfe gebeten habe.
Ich habe _serverStream.ReadTimeout = 100; auch schon auf 10 Sekunden gesetzt, es macht leider keinen Unterscheid. Außerdem teste ich momentan nur auf meinem Rechner, wo die response nicht allzu hoch sein sollte.
Es funktioniert so zwar, aber es kann ja auch nicht sein, dass es so gedacht ist, immer eine Exception zu ignorieren oder?
while (true)
{
if (_serverStream.DataAvailable)
{
int i = 0;
do
{
try
{
i = _serverStream.Read(bytes, 0, bytes.Length);
allBytes.AddRange(bytes.Take(i));
}
catch (IOException ex)
{
var socketExept = ex.InnerException as SocketException;
if (socketExept == null || socketExept.ErrorCode != 10060)
// if it's not the "expected" exception, let's not hide the error
throw ex;
// if it is the receive timeout, then reading ended
i = 0;
}
} while (i > 0);
}
else
{
break;
}
}
Du ignorierst sie nicht; Du behandelst sie. Zwei völlig verschiedene Dinge.
Dass das Timeout hier funktional gewollt ist, ist ja nachvollziehbar: read liefert halt nichts, wenn nichts da ist und wirft dann nen Timeout.
Muss sogar so gemacht werden, wenn man statt einer while schleife eine do-while nimmt.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Danke für deine Hilfe.
"Muss sogar so gemacht werden, wenn man statt einer while schleife eine do-while nimmt. "
Ich kann dir leider nicht ganz folgen, ich habe das ganze auch schon so probiert:
while ((i = _serverStream.Read(bytes, 0, bytes.Length)) != 0)
{
allBytes.AddRange(bytes.Take(i));
}
leider hatte ich dieselbe Exception und i wird nie 0. Normalerweise liefert die Funktion Read aber doch 0 zurück, sobald nichts mehr im Stream steht.
Nicht unbedingt. Read gibt nur dann 0 zurück, wenn die Gegenseite den Stream geschlossen hat.
Da ein NetworkStream aber "kein Ende kennt", sondern einfach wartet, ob nicht noch irgendwas kommt MUSS auf den Timeout reagiert werden.
Aus diesem Grund hat der NetworkStream auch die DataAvailable
-Eigenschaft.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code