Reputation: 21
I have a few problem to send jpg data using a socket.
Sender side:
Socket client_s = new Socket(AddressFamily.InterNetwork, SocketType.Stream,ProtocolType.Tcp);
IPEndPoint serverEP = new IPEndPoint(IPAddress.Loopback, 4567);
client_s.Connect(serverEP);
NetworkStream stream = new NetworkStream(client_s);
bmp.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
Receiver side:
clientSocket = listenSocket.Accept();
NetworkStream s = new NetworkStream(clientSocket);
Bitmap slice_bmp = new Bitmap(s);
Graphics g = this.CreateGraphics();
g.DrawImage(slice_bmp,0,0);
When I execute the above, Bitmap slice_bmp = new Bitmap(s);
is blocked until closing sender's socket. After sender's socket is closed, an image is drawn normally. I want to know why that operation is blocked?
Also, is it right using instance of Networkstream as argument of constructor of Bitmap? (My code is based on inheritance)
Upvotes: 0
Views: 1751
Reputation: 8656
First of all, I would suggest you to use Flush()
method of the NetworkStream
to be sure that all the data has been sent.
Socket client_s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint serverEP = new IPEndPoint(IPAddress.Loopback, 4567);
client_s.Connect(serverEP);
NetworkStream stream = new NetworkStream(client_s);
bmp.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
stream.Flush(); //flush everything
On the receiver's side, you should first read all the bytes of the image into a byte
array. From that byte array you could construct the MemoryStream
and than Bitmap
from that stream.
clientSocket = listenSocket.Accept();
NetworkStream s = new NetworkStream(clientSocket);
int bytesRead = 0;
int howMany = 0;
byte [] byteBuffer = new byte[100000];
do
{
howMany = s.Read(byteBuffer, bytesRead, 10000);
bytesRead += howMany;
if(bytesRead>=byteBuffer.Length)
byteBuffer = ResizeByteArray(byteBuffer);
}
while (howMany > 0 && s.DataAvailable);
MemoryStream ms = new MemoryStream(byteBuffer);
Bitmap slice_bmp = new Bitmap(ms);
Graphics g = this.CreateGraphics();
g.DrawImage(slice_bmp, 0, 0);
g.Dispose();
If the image is larger from the capacity of the instantiated byte array, then you need to resize it. You could use this helper method:
private byte[] ResizeByteArray(byte[] arr)
{
byte[] newArr = new byte[arr.Length * 2];
Array.Copy(arr, newArr, arr.Length);
return newArr;
}
And as a side note, always call Dispose
on Graphics
object that you create manually (like in this case). I checked the code and it works.
Upvotes: 2
Reputation: 1670
This is because bitmap class waits for transmission to end:
First receive byte data buffer separately, then create memory stream from it and then create bitmap.
Upvotes: 0
Reputation: 13207
It appears you are working on a single threaded-application, or at least on the UI-thread of a multi-threaded-application. The blocking appears because your bitmap object is waiting for its construction to be complete. And as it takes a while to read from a stream over a network, your program will not continue until your bitmap-object is fully created.
If you wanted your program to go on, you would need to create a thread and have it read from the stream and create the bitmap. When the bitmap is ready you could fire an event and act appropriately.
As NetworkStream
is a subclass of System.IO.Stream
it is perfectly fine! You can use any System.IO.Stream
to create an object that requires a stream. The only result is, as you experienced, it might take a little longer than creating the image, e.g. from a System.IO.FileStream
.
Have a look at MSDN most of the stuff is well described.
Upvotes: 0