Visitas: 319  
Tiempo total: 11 días con 23:24:14 hrs  

A continuación el código necesario para realizar una conexión utilizando sockets con un servidor C# y un cliente Android. Para este ejemplo se utilizo Visual Studio 2012, Windows 7, Eclipse Luna en Ubuntu, una red local utilizando una maquina física como servidor y un dispositivo móvil Android 2.3.3.

Servidor C#

private void button1_Click(object sender, System.EventArgs e){
comunicacion com = new comunicacion();
com.StartServer() ;
}

public class comunicacion {
TcpListener tcpListener;

public bool StartServer(){
try{
tcpListener = new TcpListener(IPAddress.Any, 5678);
tcpListener.Start();
tcpListener.BeginAcceptTcpClient(new AsyncCallback(ProcessEvents), tcpListener);
Console.WriteLine("Listing at Port "+ 5678);
}catch (Exception e){
Console.WriteLine("Error: "+e.ToString());
return false;
}
return true;
}

void ProcessEvents(IAsyncResult asyn){
try{
TcpListener processListen = (TcpListener)asyn.AsyncState;
TcpClient tcpClient = processListen.EndAcceptTcpClient(asyn);
NetworkStream myStream = tcpClient.GetStream();
if (myStream.CanRead){
StreamReader readerStream = new StreamReader(myStream);
string myMessage = readerStream.ReadToEnd();
Console.WriteLine("--------");
Console.WriteLine("Mensaje recivido: "+myMessage);
Console.WriteLine("Ip: " + ((IPEndPoint)tcpClient.Client.RemoteEndPoint).Address.ToString());
if(myMessage=="hola"){
writeData(myStream, "mundo!");
}else{
writeData(myStream, "Hola mundo!");
}
readerStream.Close();
}
myStream.Close();
tcpClient.Close();
tcpListener.BeginAcceptTcpClient(new AsyncCallback(ProcessEvents), tcpListener);
}catch (Exception e){
Console.WriteLine("error 2 " + e.ToString() );
}
}

public static void writeData(NetworkStream networkStream, string dataToClient){
Console.WriteLine("Procesando envio...");
Console.WriteLine("Mensaje: " + dataToClient);
Byte[] sendBytes = null;
try{
sendBytes = Encoding.ASCII.GetBytes(dataToClient);
networkStream.Write(sendBytes, 0, sendBytes.Length);
networkStream.Flush();
consola("Enviado correctamente");
}catch (SocketException e){
consola("Ocurrio un error");
throw;
}
}
}

El servidor funciona de la siguiente manera: Al dar clic en un botón, se utiliza la clase comunicación, al crear esta clase se inicia el socket y el método ProcessEvents se llamara a si misma de manera infinita, esto en la línea de código:

tcpListener.BeginAcceptTcpClient(new AsyncCallback(ProcessEvents), tcpListener);

En este caso estará a la espera de alguna conexión de parte de un cliente, obteniendo el mensaje en la variable myMessage, a partir de esta variable podemos responder con un mensaje utilizando el método writeData.

Cliente Java/Android

//socket
public static String ip="192.168.1.7";
public static int puerto=5678;
btn_send.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
String mensaje = txt_message.getText().toString();
//enviando mensaje
try {
Socket socket = new Socket( ip, puerto);
PrintWriter writer = new PrintWriter(socket.getOutputStream());
writer.print(mensaje);
writer.flush();
socket.shutdownOutput();
lbl_resultado.setText("#"+i+" - Mensaje enviado: "+mensaje);
/* ************ esperando respuesta ************** */
BufferedReader r = new BufferedReader(new InputStreamReader(socket.getInputStream()));
StringBuilder total = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
total.append(line);
}
lbl_respuesta.setText("Respuesta: "+total.toString());
/* ****************************** */
socket.close();
writer.close();
} catch (Exception e) {
e.printStackTrace();
lbl_resultado.setText("Error! "+e.toString());
}
//finalizo envio
i++;
}
});

El código anterior es usando Activities – XML y archivos Java dado que estamos trabajando en Android. Cuando el usuario envía el mensaje que escribe en un Textfield, se crea el socket utilizando la IP y el puerto del servidor C#. Esto es bastante fácil pero es necesaria la siguiente línea de código, que permitirá recibir los mensajes del servidor:

socket.shutdownOutput();

Significa que una vez enviado el mensaje, Android ya no enviara ninguno mas, haciendo que C# pueda empezar a responder. Una vez se recibe el mensaje, el socket finaliza. Si no se utiliza esta instrucción, C# se quedara en un estado de espera de más mensajes, lo cual hace que Android también entre en un estado de espera de una respuesta por parte de C#.

Android y C#

Una de las configuraciones que hay que hacer, es permitirle a la aplicación móvil la utilización de internet para que pueda responder correctamente. Para esto, agregamos en el archivo Manifest del proyecto de Android:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

De igual manera, hay que habilitar el puerto 5678 en el cortafuegos de Windows.

Finalizando

Debo de agregar, que para este ejemplo Visual Studio 2012 presento problemas de compatibilidad en Windows 8, en general no afectan en la mayoría de aplicaciones pero para esta conexión utilizando Sockets el proceso svhosts.exe, que se encarga de gestionar estas conexiones y es creado por la aplicación que se desarrolla, imposibilita la conexión, haciendo que la aplicación deje de responder y se cierre. Esto utilizando una maquina de 64 bits.

También puedo mencionar, que el método ProcessEvents del servidor C#, se crea en un proceso diferente al cual pertenecen los elementos gráficos (De por ejemplo) una ventana, así que si queremos ver los mensajes en un Label o Textfield, nos mostrara el problema que ambos elementos no pertenecen al mismo proceso en el cual fueron creados.

En una futura publicación, mostrare lo básico para permitir la comunicación entre las distintas clases que pueden conformar un proyecto, comunicación de hijo a padre, comunicación entre procesos, mostrar o ocultar la consola en un proyecto de formularios y otras facilidades que se logran al utilizar correctamente una estructura orientada a objetos en C#.