Asynchronous image transfer over TCP/IP socket

K

keksy

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top