Link to home
Start Free TrialLog in
Avatar of mSchmidt
mSchmidt

asked on

PDA C# .NET - Communicate instantly with pc, how ?

Hi

I have a PDA application where i need to validate and get data from a PC, this has to happen very fast.
The PDAs have a Wifi connection and currently i have done this using a Socket connection.
However iam having huge problems when i run my code and the PDA for some reason cant find the server (wifi not connected, server down, bad connection or whatever)
When this happens my entire application freezes.

Iam wondering whether its the best way to do this communication as a socket or if there is something else i should look into ?

My current implemtation is as follows:


public class AsynchronousClient
	{
 
		// The port number for the remote device.
		public static Int32 port;
        public static frm_softwarestart tMain;
		public static IPAddress address;
 
		public static Boolean Init(IConfigSource Config)
		{
			string a = Config.Configs["Setup"].Get("IP Address");
			try
			{
				address = IPAddress.Parse(a);
			}
			catch
			{
				MessageBox.Show("IP adressen er ikke korrekt", Properties.Resources.FlexyOrder);
				return false;
			}
 
			port = Config.Configs["Setup"].GetInt("Port", 0);
			if (port <= 0)
			{
				MessageBox.Show("Port nr. er ikke korrekt", Properties.Resources.FlexyOrder);
				return false;
			}
 
			return true;
           
		}
        public static string openAndSendRequest(String Command)
        {
            AsynchronousClient Comm = new AsynchronousClient();
            Comm.SendRequest(Command);
            return Comm.response;
        }
		// ManualResetEvent instances signal completion.
		private ManualResetEvent connectDone = new ManualResetEvent(false);
		private ManualResetEvent sendDone = new ManualResetEvent(false);
		private ManualResetEvent receiveDone = new ManualResetEvent(false);
 
		// The response from the remote device.
		public String response = String.Empty;
 
		public void SendRequest(String Command)
		{
            if (!tMain.netOnline)
            {
                response = "NOCONNECTION";
                return;
            }
			// Establish the remote endpoint for the socket.
			IPAddress ipAddress = new IPAddress(address.GetAddressBytes());
			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.
			try {
			    connectDone.Reset();
                client.BeginConnect(remoteEP,new AsyncCallback(ConnectCallback), client);
				connectDone.WaitOne();
			}
			catch
			{
				response = "NOCONNECTION";
				return;
			}
			if (!client.Connected) {
                response = "NOCONNECTION";
                return;
			}
 
 
			// Send data to the remote device.
			sendDone.Reset();
			Send(client, Command + "<EOF>");
			sendDone.WaitOne();
 
			// Receive the response from the remote device.
			try
			{
				receiveDone.Reset();
				Receive(client);
				receiveDone.WaitOne();
			}
			catch
			{
				response = "NOREPLY";
			}
 
			// Release the socket.
			client.Shutdown(SocketShutdown.Both);
			client.Close();
		}
 
		private void ConnectCallback(IAsyncResult ar)
		{
			// Retrieve the socket from the state object.
			Socket client = (Socket)ar.AsyncState;
			
			if(client.Connected) {
			    // Complete the connection.
			    client.EndConnect(ar);
            }
			// Signal that the connection has been made.
			connectDone.Set();
		}
 
		private void Receive(Socket client)
		{
			// Create the state object.
			StateObject state = new StateObject();
			state.workSocket = client;
 
			// Begin receiving the data from the remote device.
			client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
				new AsyncCallback(ReceiveCallback), state);
		}
 
		private void ReceiveCallback(IAsyncResult ar)
		{
			// Retrieve the state object and the client socket 
			// from the asynchronous state object.
			StateObject state = (StateObject)ar.AsyncState;
			Socket client = state.workSocket;
 
			// Read data from the remote device.
			Int32 bytesRead = client.EndReceive(ar);
			if (bytesRead > 0)
			{
				// There might be more data, so store the data received so far.
                state.sb.Append(Encoding.Default.GetString(state.buffer, 0, bytesRead));
 
				// Get state.sbthe rest of the data.
				client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
					new AsyncCallback(ReceiveCallback), state);
			}
			else
			{
				// All the data has arrived; put it in response.
				if (state.sb.Length > 1)
				{
					response = state.sb.ToString();
				}
				// Signal that all bytes have been received.
				receiveDone.Set();
			}
		}
 
		private void Send(Socket client, String data)
		{
			// Convert the String data to byte data using UTF7 encoding.
            byte[] byteData = Encoding.Default.GetBytes(data);
            
			// Begin sending the data to the remote device.
            client.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), client);
        }
 
		private void SendCallback(IAsyncResult ar)
		{
 
			// Retrieve the socket from the state object.
			Socket client = (Socket)ar.AsyncState;
 
			// Complete sending the data to the remote device.
			Int32 bytesSent = client.EndSend(ar);
 
			// Signal that all bytes have been sent.
			sendDone.Set();
		}
	}

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Anurag Thakur
Anurag Thakur
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of mSchmidt
mSchmidt

ASKER

Okay, so you think doing it the socket way is the best approach ?
i cannot comment it but there are other ways too like remoting (TCP based or IIS based) or a web service can also be used
i havent used sockets myself so i cannot comment on it but remoting - TCP or IIS based i have used to a good effect and the performance was also good
Okay, but using Remoting you will have some overhead made by the framework, which in turn would make it slower ?, or am i wrong ?
I looked through the implementation of the Ping you gave me earlier, it would add major overhead as well.
It is actually implemented using a Socket, so it would just result in two sockets being established for one transaction.
However i found this line within the code:
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, this.pingTimeout);

Which would allow me to change my timeout to say 1 or 3 seconds i guess .
Which in turn would make my application react very if it cannot locate the server.
as i previously mentioned that i dont have experience in sockets
its very good if you found the solution for avalibility of the server using SocketOptions only