Reputation: 333
I have a client application and a server application. The client application activates this function every 40 milliseconds: *Note that nstream is a NetworkStream instance.
private void SendScreen(NetworkStream nstream)
{
StreamWriter writer = new StreamWriter(nstream);
ScreenCapture sc = new ScreenCapture();
System.Drawing.Image img = sc.CaptureScreen();
MemoryStream ms = new MemoryStream();
img.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
byte[] buffer = new byte[ms.Length];
ms.Seek(0, SeekOrigin.Begin);
ms.Read(buffer, 0, buffer.Length);
Console.WriteLine(buffer.Length);
writer.WriteLine(buffer.Length);
writer.Flush();
nstream.Write(buffer, 0, buffer.Length);
}
and this is the server application code for receiving the image:
private async void ShowImage()
{
while (true)
{
string num = await reader.ReadLineAsync();
Console.WriteLine(num);
int ctBytes = int.Parse(num);
byte[] buffer = new byte[ctBytes];
await stream.ReadAsync(buffer, 0, buffer.Length);
MemoryStream ms = new MemoryStream(buffer);
Image img = Image.FromStream(ms);
Bitmap bmp = new Bitmap(img);
this.Height = bmp.Height;
this.Width = bmp.Width;
this.BackgroundImage = bmp;
}
}
I can't think of any parts that disturbs these actions. In the first iteration of the server application, everything works (although I see black screen instead of the screenshot - but the number of bytes sent and received- matches.) At the second iteration when I writeline num, it shows jibberish and then stops (because it cannot be parsed to int).
Upvotes: 0
Views: 2306
Reputation: 1418
Essentially I suspect you have a sync problem as I had, when I attempted to reproduce your problem (successfully).
Be it a Header
or a single Integer
that announces an upcomming Bitmap
transmission. It's all terribly easy to get out of sync.
Unless you want to dive into network synchronization and flow control I recommend to use a single TransmissionObject
for every transmission between the server and the client (and maybe another vice versa)
That Object has the potential to store any data that has to be transmitted. (via inheritance)
Finally when putting the Object on the network stream you may use any consistent Serializer
The Serializer
does all the work of syncing up the information to where it is needed (Meta information like length and finally the content aswell)
Well in my repro project I came up with this Class to hold the Bitmap.
As an example to how to use it on the Server:
public void Send(Bitmap bmp)
{
// prepare Bitmap
BitmapTransmission bt = new BitmapTransmission(bmp);
// try transmitting the object
try
{
// lock to exclude other Threads of using the stream
lock (m_objSendLock)
{
bt.Send(m_stream);
}
}
catch (BitmapTransmissionException ex)
{ // will catch any exception thrown in bt.Send(...)
Debug.Print("BitmapHeaderException: " + ex.Message);
///BitmapTransmissionException provides a Property `CloseConnection`
/// it will inform you whether the Exception is recoverable
}
}
Where m_objSendLock
is an Object to prevend concurrent access on the network stream.
m_stream
is the NetworkStream connected to the Client.
Echo
is a logging mechanism.
The client may receive such transmissions via
public void Receive() {
BitmapTransmission bt = bt.Receive(m_stream);
// check for exceptions maybe?
pictureBox1.Image = bt.Bitmap;
}
Where as again m_stream
it the NetworkStream connected to the Server.
If you want to have a look at the (messy but working) repro project do tell so.
Upvotes: 1