471,311 Members | 1,816 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,311 software developers and data experts.

Asynchronous image transfer over TCP/IP socket

Hi every1,

I am writing a small client/server application and in it I want to
send an image asynchronous from the client to the server through a TCP
socket. I found an example code on the MSDN site, which is actually
for sending strings. I tried to adapt this code so that the client
sends an image instead of a string. However, there is something wrong
on the server side (i guess)...
The server starts listening, the client starts sending and I become an
indication, that the server receives something... but doesn't stop
receiving. The else-condition in the function Send_Image() is never
reached.

As far as I understood the Microsoft-code, the data is being sent in
parts (every part is with the size of the buffer). That's why the
Read_Image() function is called as long as all the data is transfered
(that is exactly the if-condition - if bytesRead>0 ). I save these
data parts (in bytes) in an ArrayList and at the end I convert this
ArrayList to a byte array and then to a Bitmap.

Here is the code. Can anyone help me to find my mistake ... please, I
am stuck!!! :(
The client side:

public static void StartClient()
{
// Connect to a remote device.
try
{
// Establish the remote endpoint for the socket.
// The name of the remote device is "host.domain.com".
IPHostEntry ipHostInfo =
Dns.Resolve("host.domain.com");
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);

// Create a TCP/IP socket.
Socket client = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);

// Connect to the remote endpoint.
client.BeginConnect(remoteEP,
new AsyncCallback(ConnectCallback), client);
connectDone.WaitOne();

// Send the image to the remote device.
string fName = @"\Program Files\Client\image.jpg"; //
path to image
SendImage(client, new Bitmap(fName));
sendDone.WaitOne();

// Receive the response from the remote device.
Receive(client);
receiveDone.WaitOne();

// Write the response to the console.
Console.WriteLine("Response received : {0}",
response);
//System.Windows.Forms.MessageBox.Show("Otgovor
poluchen");

// Release the socket.
client.Shutdown(SocketShutdown.Both);
client.Close();

}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
//--------------------------------------------------------------------
//convet Image to byte[]
public static byte[] imageToByteArray(Bitmap imageIn)
{
MemoryStream ms = new MemoryStream();
imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
return ms.GetBuffer();
}
//--------------------------------------------------------------------
private static void SendImage(Socket client, Bitmap img)
{
// Convert the image to byte data
byte[] byteData = imageToByteArray(img);

// Begin sending the data to the remote device.
client.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), client);
}
//--------------------------------------------------------------------
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;

// Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
Console.WriteLine("Sent {0} bytes to server.",
bytesSent); //this msg never shows up!

// Signal that all bytes have been sent.
sendDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
The server side:

// State object for reading client data asynchronously
public class StateObject {
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 1024*10;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received image bytes
public ArrayList imageBytes = new ArrayList();
}
//----------------------------------------------------------------------
public static void StartListening() {
// Data buffer for incoming data.
byte[] bytes = new Byte[1024];

// Establish the local endpoint for the socket.
// The DNS name of the computer running the listener is
"server.domain.com".
IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);

// Create a TCP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp );

// Bind the socket to the local endpoint and listen for
incoming connections.
try {
listener.Bind(localEndPoint);
listener.Listen(100);

while (true) {
// Set the event to nonsignaled state.
allDone.Reset();

// Start an asynchronous socket to listen for
connections.
System.Windows.Forms.MessageBox.Show("Waiting for a
connection...");
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener );

// Wait until a connection is made before continuing.
allDone.WaitOne();
}

} catch (Exception e) {
Console.WriteLine(e.ToString());
System.Windows.Forms.MessageBox.Show(e.ToString()) ;
}

System.Windows.Forms.MessageBox.Show("\nPress ENTER to
continue...");
Console.Read();

}
//----------------------------------------------------------------------
public static void AcceptCallback(IAsyncResult ar) {
// Signal the main thread to continue.
allDone.Set();

// Get the socket that handles the client request.
Socket listener = (Socket) ar.AsyncState;
Socket handler = listener.EndAccept(ar);

// Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive( state.buffer, 0, StateObject.BufferSize,
0,
new AsyncCallback(Read_Image), state);
}
//--------------------------------------------------------
public static void Read_Image(IAsyncResult ar)
{
StateObject so = (StateObject)ar.AsyncState;
Socket s = so.workSocket;

int read = s.EndReceive(ar);

if (read 0)
{
//so.sb.Append(Encoding.ASCII.GetString(so.buffer, 0,
read));
foreach (byte el in so.buffer)
{
so.imageBytes.Add(el);
}
s.BeginReceive(so.buffer, 0, StateObject.BufferSize, 0,new
AsyncCallback(Read_Image), so);
System.Windows.Forms.MessageBox.Show("read 0, call
Read_Image recursively");
}
else
{
System.Windows.Forms.MessageBox.Show("Else case");
if (so.imageBytes.Count 0)
{
//All of the data has been read, so displays it to the
console
byte[] imageBytesArray = new
byte[so.imageBytes.Count];
so.imageBytes.CopyTo(imageBytesArray);
myForm.pictureBox1.Image =
ImgConverter.byteArrayToImage(imageBytesArray);
//Send(s, "<EOF>");
//System.Windows.Forms.MessageBox.Show("Sent!");
}
System.Windows.Forms.MessageBox.Show("Receive done!");
Send(s, "<EOF>"); //this sends a msg to the client and
closes the socket connection. I didn't paste the function
s.Close();
}
}


Thanks in advance!

Cheers,
Vasil
Sep 8 '08 #1
1 6811
On Mon, 08 Sep 2008 15:11:04 -0700, keksy <va***********@gmail.comwrote:
[...]
As far as I understood the Microsoft-code, the data is being sent in
parts (every part is with the size of the buffer). That's why the
Read_Image() function is called as long as all the data is transfered
(that is exactly the if-condition - if bytesRead>0 ). I save these
data parts (in bytes) in an ArrayList and at the end I convert this
ArrayList to a byte array and then to a Bitmap.

Here is the code. Can anyone help me to find my mistake ... please, I
am stuck!!! :(
It's hard to say, as you didn't post a concise-but-complete code sample.
But a few things jump out at me during a cursory scan of the code (it's
too sloppy for me to try to decipher every individual statement):

-- You're using the async API to do this. As much as I am a big fan
of the async API for network i/o, you should first get it working
synchronously. And especially for an example such as this one, where all
you wind up doing is waiting at checkpoints in one thread for another
thread to finish. That's just silly. If a thread is just waiting on
another thread, it could instead be doing the work that other thread is
doing, saving you a thread.

-- You are doing unnecessary work processing the image file. Just use
FileStream to read it, and send the bytes directly from the file, rather
than doing all that stuff with the Bitmap class.

-- More importantly, I see nothing in the code you posted that would
cause the main thread to wait for the connection to actually be
established before it tries to start sending. I'm surprised you don't get
an exception (if you really don't, maybe there's a subtle bug in .NET),
but in any case you definitely should not call BeginSend() on the socket
until after you've called EndConnect().

Of course, had you just implemented it synchronously, you wouldn't have
made that mistake. :)

Pete
Sep 8 '08 #2

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

reply views Thread by Richard | last post: by
9 posts views Thread by Michael Lindsey | last post: by
7 posts views Thread by Colin | last post: by
4 posts views Thread by Engineerik | last post: by
2 posts views Thread by Nicolas Le Gland | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.