2017-02-06 7 views
0

Ich sende ein Bild (insbesondere einen Screenshot) über einen tcpclient/networkstream. Um die Bildbytes korrekt auf der Empfangsseite zu lesen, muss ich die Länge des Bildes kennen. Ich beabsichtige, die ersten 6 Bytes des Puffers für die Bildgröße zu speichern (da es nie 6 Zahlen zu überschreiten scheint), und dann von dort den Rest des Puffers als das Bild. Das Problem, das ich habe, ist, ich bin nicht in der Lage, nur die ersten 6 Bytes zu lesen.Erste 6 Bytes von NetworkStream lesen?

Server-Code

 int data = 0; 

     byte[] readBuffer = new byte[getSelectedClient().ReceiveBufferSize]; 

     **data = stream.Read(readBuffer, 0, 5, readBuffer.Length);** <-- sort of thing im trying to do 

     string pictureSize = Encoding.ASCII.GetString(readBuffer, 0, data); 

     Console.WriteLine(pictureSize); //for debugging purposes 

     string x = new Random().Next().ToString(); 

     FileStream f = new FileStream(x + ".bmp", FileMode.Create, FileAccess.Write); 

     while (new FileInfo(x + ".bmp").Length != Convert.ToInt32(pictureSize)) 
     { 
      **data = stream.Read(readBuffer, 6, readBuffer.Length);** <-- then it would read from the 6th byte, which would be the start of the image 
      f.Write(readBuffer, 0, data); 
     } 

     f.Close(); 

     Process.Start(x + ".bmp"); 

     screenShotBTN.Enabled = true; 

-Client-Code

MemoryStream ms = new MemoryStream(); 
Bitmap bitmap = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height); 
Graphics graphics = Graphics.FromImage(bitmap); 
graphics.CopyFromScreen(0, 0, 0, 0, bitmap.Size); 
bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); 
       writeToStream(combineBytes(Encoding.ASCII.GetBytes(ms.Length.ToString()), ms.ToArray())); 
ms.Close(); 


public static byte[] combineBytes(byte[] b1, byte[] b2) 
    { 
     byte[] b3 = new byte[b1.Length + b2.Length]; 
     Array.Copy(b1, 0, b3, 0, b1.Length); 
     Array.Copy(b2, 0, b3, b1.Length, b2.Length); 
     return b3; 
    } 

Antwort

1

Was Sie implementieren Länge vorangestellt Messaging ist.

Dinge zu erinnern sind, dass, wenn Sie aus einem Netzwerkstream lesen, Sie nicht unbedingt alle Bytes erhalten, die Sie sofort suchen (die meisten Zeiten, wenn Sie lokal testen alles wird, aber Sie müssen für die Programmierung Möglichkeit, dass Sie im schlimmsten Fall nur 1 Byte erhalten).

Daher sollten Sie in einen Zustand (warten Sie auf Länge, Warten auf Payload) gehen. Dann beginnen Sie mit dem Lesen von Bytes in der erwarteten Länge und bauen dann diese Daten in einem Puffer auf. Sobald Sie Ihre Länge haben (6 Bytes in Ihrem Fall), können Sie den Status auf "Warten" setzen, dann lesen Sie dies in Ihren Sekundärpuffer, bis Sie die volle Nutzlast haben und dann können Sie loslegen.

Es könnte sich lohnen, die Artikel von Stephen Cleary über das Framing von Nachrichten zu lesen. Ich lerne viel über Vernetzung durch das Lesen dieser.

http://blog.stephencleary.com/2009/04/sample-code-length-prefix-message.html

0

löste ich das Problem auf eigene Faust.

Server

int data = 0; 

byte[] readBuffer = new byte[getSelectedClient().ReceiveBufferSize]; 

data = stream.Read(readBuffer, 0, 6); //only read first 6 

string pictureSize = Encoding.ASCII.GetString(readBuffer, 0, data); 

Console.WriteLine(pictureSize); //for debugging purposes 

string x = new Random().Next().ToString(); 

FileStream f = new FileStream(x + ".bmp", FileMode.Create, FileAccess.Write); 

while (new FileInfo(x + ".bmp").Length != Convert.ToInt32(pictureSize)) 
{ 
    data = stream.Read(readBuffer, 0, readBuffer.Length); 
    f.Write(readBuffer, 0, data); 
} 

f.Close(); 

Process.Start(x + ".bmp"); 

screenShotBTN.Enabled = true; 

Client-Code

MemoryStream ms = new MemoryStream(); 
Bitmap bitmap = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height); 
Graphics graphics = Graphics.FromImage(bitmap); 
graphics.CopyFromScreen(0, 0, 0, 0, bitmap.Size); 
bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); 
Console.WriteLine(ms.Length.ToString()); 
writeToStream(combineBytes(Encoding.ASCII.GetBytes(ms.Length.ToString()), ms.ToArray())); 
ms.Close(); 
+0

nur ein Tipp, wenn Sie Daten über Netzwerke senden, können Sie Bytes statt der Zeichen senden. Eine Ganzzahl (int.minvalue -> int.maxvalue), die auf der Wire angegeben ist, beträgt 4 Bytes. –

+0

Würdest du das ausarbeiten können? (Ich bin etwas verwirrt darüber, was du meinst, ein Beispiel würde helfen, da ich auf diese Weise besser zu lernen scheint) – rrrrrrrrrrrrrrrr

+0

In deiner wirteToStream konvertierst du deine Länge in eine Zeichenkette. Dann werden die Bytes der Zeichenfolge abgerufen, die die Nummer darstellt. Verwenden Sie stattdessen BitConverter.GetBytes (int), anstatt in eine Zeichenfolge zu konvertieren. Wenn Sie ein Int in Bytes konvertieren, wird es immer 4 sein. –

Verwandte Themen