Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


¿Cómo puedo manejar múltiples clientes conectados a un servidor mediante sockets?

Tengo una aplicación para Android que necesita conectar varios dispositivos. Un dispositivo debe actuar como el propietario del grupo y dar instrucciones a todos los clientes para hacer cosas específicas. Supongo que es comparable a un juego inalámbrico de mano donde un jugador es el anfitrión.

Tengo un par de preguntas por lo que voy a tratar de mantenerlos conciso. Incluso una respuesta a la primera ayudaría.

Primero, he emparejado con éxito un solo servidor y un solo teléfono del cliente usando zócalos. Lo hice usando la tecnología Wi-Fi Direct de Android (se describe aquí ). El tutorial es útil, pero lamentablemente no es muy completo, en particular en la descripción de conexiones uno a muchos. Una vez que se encuentra una lista de pares, se pueden abrir las conexiones de socket. Pude conectar dos dispositivos usando un hilo para el servidor ( usando este ejemplo ), así:

public class ServerThread implements Runnable { public void run() { (Code...) client = serverSocket.accept(); (...other code here.) } } 

Un cliente se crea después de pulsar un botón (creo, todavía tratando de obtener mi cabeza alrededor de mi código modificado):

 public class MusicClientThread implements Runnable { Socket socket = new Socket(serverAddr, port); while (connected) { //(Other code here.) while ((line = in.readLine()) != null) { //While there are still messages coming } } socket.close(); //(Other code here too.) } 

Así que supongo que mi primera pregunta es: ¿Cómo puedo permitir que más clientes se conecten? Mi ServerThread se refiere a una sola variable de cliente por encima de lo que no veo cómo permitiría un número variable (mi aplicación está apuntando para cualquier cosa de 2 a 10 usuarios) ni sé la forma correcta de diferenciar entre todos mis diferentes clientes. Mi única conjetura es que utilizaría la dirección IP única de cada teléfono.

Mi segunda pregunta es, una vez que he establecido una conexión con varios clientes / compañeros, ¿cómo enviaría y recibiría las instrucciones correctamente? Actualmente mi único servidor espera una instrucción, y al recibirla, emite una instrucción de respuesta. Lo necesito para que el servidor pueda enviar instrucciones desde el principio, utilizando pulsaciones de botón, y el resultado de éstas es visible en los dispositivos cliente.

¡Espero haber aclarado todo!

  • ¿Cómo obtengo un descubrimiento de servicio Wi-Fi punto a punto para trabajar?
  • ¿Cómo cambiar el nombre del dispositivo en WiFi p2p directo?
  • Wi-Fi Directo y "normal" Wi-Fi - ¿Diferentes MAC?
  • Conecte 2 o más clientes de Android directamente
  • Transmisión por Wi-Fi Direct
  • Cómo encontrar el nombre de archivo de un archivo que se transfiere a través de wifi modo directo en Android?
  • Cómo imprimir un archivo de texto con WiFi Direct
  • WiFi-Comunicación directa entre Mac / Windows y Android
  • 2 Solutions collect form web for “¿Cómo puedo manejar múltiples clientes conectados a un servidor mediante sockets?”

    Tienes que iniciar un nuevo subproceso para cada cliente, ya que los sockets necesitan un subproceso para que se ejecuten (ya que espera la entrada la mayor parte del tiempo). Esto puede hacerse por ejemplo (de esta manera simplificada):

     public class ThreadHandler extends Thread { private ArrayList<ServerThread> serverThreads = new ArrayList<ServerThread>(); public void run() { while (!isInterrupted()) { //You should handle interrupts in some way, so that the thread won't keep on forever if you exit the app. (Code...) ServerThread thread = new ServerThread(serverSocket.accept()); serverThreads.add(thread); thread.start(); } } public void doSomethingOnAllThreads() { for (ServerThread serverThread : serverThreads) { serverThread.otherMethod(); } } } 

    Donde el ServerThread se parece a algo así:

     public class ServerThread extends Thread { private Socket socket; public ServerThread(Socket socket) { this.socket = socket; } public void run() { (...other code here.) } public void otherMethod() { //Signal to the thread that it needs to do something (which should then be handled in the run method) } } 

    Tengo una Google TV Box. Y tengo dos teléfonos móviles.

    En GoogleTV Box ejecuto un servidor. El servidor tiene un ServerSocket en el puerto 6001. También el servidor tiene dos sockets para dos clientes

    El primer dispositivo se conecta al servidor y el uso de la toma número uno el segundo el otro ….

    Puedo simultanous publicar los mensajes diffrent de 2 dispositivos al zócalo de la caja de la google TV y demostrarlos en la TV.

    Estoy usando la siguiente solución:

    PARA EL CLIENTE MÓVIL (2 dispositivos)

    Crear un nuevo proyecto androide con una actividad en blanco y copiar este código en. Crear un diseño para el cliente que contiene un edittext y un botón. ASEGÚRESE DE CONFIGURAR INTERNET Y ACCEDER A PERMISOS DE RED EN ANDROIDMANIFEST.XML !!! Y edite serverIpAddress en este archivo a su IP accesible servidores.

     package de.android.googletv.gameclient; import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; import java.util.Random; import android.app.Activity; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; /** * * * */ public class FullscreenActivity extends Activity { private Socket socket; private String serverIpAddress = "192.168.22.253"; // GOOGLE TV IP private static final int PLAYER_1_SERVERPORT = 6001; private Button bt; private TextView tv; String DEVICE_NAME; private class ConnectToServer extends AsyncTask { @Override protected Object doInBackground(Object... params) { System.out.println("connecting to server..."); try { InetAddress serverAddr = InetAddress.getByName(serverIpAddress); socket = new Socket(serverAddr, PLAYER_1_SERVERPORT); } catch (UnknownHostException e1) { System.out.println("ERROR REACHING SERVER! 1"); e1.printStackTrace(); } catch (IOException e1) { System.out.println("ERROR REACHING SERVER! 2"); e1.printStackTrace(); } System.out.println("Done!"); return params; } protected void onPostExecute() { } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_fullscreen); DEVICE_NAME = android.os.Build.MODEL; Button exit = (Button) findViewById(R.id.dummy_button); exit.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { System.exit(1); } }); new ConnectToServer().execute(""); tv = (TextView) findViewById(R.id.editText1); bt = (Button) findViewById(R.id.button1); bt.setOnClickListener(new OnClickListener() { public void onClick(View v) { try { Random rnd = new Random(); EditText et = (EditText) findViewById(R.id.editText1); String str = DEVICE_NAME + " ID" + rnd.nextInt() + " says: " + et.getText().toString(); PrintWriter out = new PrintWriter( new BufferedWriter( new OutputStreamWriter( socket.getOutputStream())),true ); out.println(str); Log.d("Client", "Client sent message"); } catch (UnknownHostException e) { tv.setText("UnknownHostException"); e.printStackTrace(); } catch (IOException e) { tv.setText("IOException"); e.printStackTrace(); } catch (Exception e) { tv.setText("Exception"); e.printStackTrace(); } } }); } } 

    PARA EL SERVIDOR (google tv box)

    Crear un nuevo proyecto androide con actividad en blanco y copiar este código en. Crear un diseño con sólo un textfield Asegúrese de configurar Internet y acceso a la red PERMISIONES EN ANDROIDMANIFEST.XML!

     package de.android.googletv.gameserver; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; /** * * * */ public class FullscreenActivity extends Activity { // server socket ServerSocket ss_plr1 = null; public static final int SERVERPORT_1 = 6001; int nr_connections = 0; // socket for player1 Socket s1; // socket for player2 Socket s2; Thread myCommsThread = null; protected static final int MSG_ID = 0x1337; String mClientMsg = ""; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_fullscreen); Button exit = (Button) findViewById(R.id.dummy_button); exit.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { System.exit(1); } }); TextView tv = (TextView) findViewById(R.id.fullscreen_content); tv.setText("Nothing from client yet"); myCommsThread = new Thread(new CommsThread()); myCommsThread.start(); } @Override protected void onStop() { super.onStop(); try { // make sure you close the socket upon exiting ss_plr1.close(); } catch (IOException e) {e.printStackTrace(); } } Handler myUpdateHandler = new Handler() { public void handleMessage(Message msg) { System.out.println("handleMessage("+msg+")"); switch (msg.what) { case MSG_ID: TextView tv = (TextView) findViewById(R.id.fullscreen_content); tv.setText((String)msg.obj); break; default: break; } super.handleMessage(msg); } }; class CommsThread implements Runnable { public void run() { System.out.println("creating new sockets..."); try { ss_plr1 = new ServerSocket(SERVERPORT_1 ); if (s1 == null) s1 = ss_plr1.accept(); if (s2 == null) s2 = ss_plr1.accept(); } catch (IOException e) {e.printStackTrace();} new Thread(new ConnectionHandler(s1, myUpdateHandler)).start(); new Thread(new ConnectionHandler(s2, myUpdateHandler)).start(); } } } 

    … y requerido por el servidor es el manejador de conexión para la mensajería …

    Crear una clase adicional en el proyecto de servidor denominado: "ConnectionHandler.java" y copiar este código en. Maneja las conexiones asíncronas.

     package de.android.googletv.gameserver; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; import android.os.Handler; import android.os.Message; public class ConnectionHandler implements Runnable { Socket m_socket; Handler m_updateHandler; public ConnectionHandler(Socket socket, Handler updateHandler) { m_socket = socket; m_updateHandler = updateHandler; } @Override public void run() { while (!Thread.currentThread().isInterrupted()) { try { BufferedReader input = new BufferedReader(new InputStreamReader(m_socket.getInputStream())); String st = null; st = input.readLine(); Message m = new Message(); m.what = 0x1337; m.obj = st; m_updateHandler.sendMessage(m); } catch (IOException e) { e.printStackTrace();} } } } 

    Esta no es la mejor solución. Múltiples "no agradable" codificaciones. System.exit (1) por ejemplo. Y es sólo tiene dos dispositivos de apoyo. Pero funciona para más de un dispositivo, e im bastante seguro usted lo modificará para usted propósitos. Su basado en tres fuentes de la tela y los tentativos adicionales de mí mismo para hacerla trabajar. Es sólo mi prototipo ….

    NO PUEDO ENLAZAR A ELLOS: (… a menos reputación.

    Si usted construye y ejecuta everthing debe verse como esto:

    https://plus.google.com/u/0/109268217221135029753/posts/3iz6SF1hiJa

    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.