write socket open multiple clients java android sockets tcp stream

socket - tcp server java



Escritura de audio al servidor a través de socket TCP (4)

Estoy tratando de transmitir la grabación del micrófono en tiempo real al servidor a través del socket TCP y el servidor para escribir la secuencia de entrada en un archivo. La conexión se estableció pero después de un tiempo, obtengo un error de conexión rechazada en mi lado del cliente.

Código del servidor:

public class auServer extends Thread{ private static ServerSocket serverSocket; private static int port = 3333; public void run() { System.out.println("init success"); while(true) { try { serverSocket = new ServerSocket(port); serverSocket.setSoTimeout(10000); Socket clientSoc = serverSocket.accept(); System.out.println("Waiting for client on port " +serverSocket.getLocalPort() + "..."); System.out.println("Just connected to " + clientSoc.getRemoteSocketAddress()); InputStream in = clientSoc.getInputStream(); while(in!=null) { writeToFile(in); } System.out.println("socket"); clientSoc.close(); }catch(SocketTimeoutException s) { System.out.println("Socket timed out!"); break; }catch(IOException e) { e.printStackTrace(); System.out.println("some io"); break; } catch (Exception e) { System.out.println("some e"); e.printStackTrace(); } } } private void writeToFile(InputStream in) throws IOException { // Write the output audio in byte String filePath = "8k16bitMono1.wav"; short sData[] = new short[1024]; byte[] bData = IOUtils.toByteArray(in); FileOutputStream os = null; try { os = new FileOutputStream(filePath); } catch (FileNotFoundException e) { e.printStackTrace(); } System.out.println("Short wirting to file" + sData.toString()); try { os.write(bData, 0, 2048); } catch (IOException e) { e.printStackTrace(); } try { os.close(); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { // TODO Auto-generated method stub try { Thread serverThread = new auServer(); serverThread.run(); System.out.println("runing"); }catch(IOException e){ e.printStackTrace(); } } }

y cliente:

private void streamData(byte[] bData) throws UnknownHostException, IOException, InterruptedException { //bData is byte array to transmit Thread.sleep(500); Socket client = new Socket("10.221.40.41",3333); OutputStream outToServer = client.getOutputStream(); outToServer.write(bData); if(!isRecording) client.close(); }

¿Cual podría ser el problema? Gracias por adelantado.


La creación del servidor debe realizarse fuera del bucle. Y para las conexiones paralelas necesitas iniciar un hilo por conexión.

También aplicar el tiempo de espera a las conexiones establecidas. Un tiempo de espera en el serverSocket terminará de aceptar después del tiempo de espera, esto no es lo que desea en un servidor.

... public void run() { ServerSocket serverSocket; try { serverSocket = new ServerSocket(port); } catch (Exception ex) { ex.printStackTrace(); return; } System.out.println("init success"); while (true) { try { System.out.println("Waiting for client on port " + serverSocket.getLocalPort() + "..."); final Socket clientSoc = serverSocket.accept(); clientSoc.setSoTimeout(10000); System.out.println("Just connected to " + clientSoc.getRemoteSocketAddress()); new Thread() { public void run() { try { InputStream in = clientSoc.getInputStream(); writeToFile(in); } catch (Exception e) { e.printStackTrace(); } finally { try { clientSoc.close(); } catch (Exception ignore) { } } } }.start(); } catch (Exception ex) { ex.printStackTrace(); } } } ...


Me di cuenta de la solución. El problema fue en realidad con el bloqueo de E / S de red debido a un flujo codificado incorrectamente.

Lo que me perdí fue

InputStream in = clientSoc.getInputStream(); DataInputStream DataIn =new DataInputStream(in) while(DataIn!=null) { writeToFile(DataIn); }

y el lado del cliente también

OutputStream outToServer = client.getOutputStream(); DataOutputStream out = new DataOutputStream(outToServer); out.write(sData);


Supongo que su lado del cliente es una aplicación de Android. Una vez, intenté leer y escribir datos en una aplicación de Android a través de una conexión de socket. Finalmente, lo hice utilizando el adb (android debugger bridge).

Digamos que hay una aplicación java que crea un Socket con el número de puerto 1992. Y hay una aplicación para Android, que crea un ServerSocket con el número de puerto 1993.

¡Aquí viene el verdadero negocio!

Antes de comenzar a ejecutar aplicaciones, debe ejecutar el siguiente comando en el shell adb (o puede ubicar su adb en cmd / terminal y ejecutar el comando)

adb forward tcp:1992 tcp:1993

Después de reenviar el puerto, puede escribir y leer datos de la aplicación java a la aplicación de Android y, por el contrario, mediante el uso de flujos IO de sockets.

Fragmento de código de la aplicación de escritorio:

while (flag) { try { final Socket socket = new Socket("localhost", 1992); new Thread(){ @Override public void run() { while (flag) { try { new PrintWriter(socket.getOutputStream(), true).println(new Date().toString()); } catch (IOException ex) { break; } } } }.start(); } catch (IOException ex) { // need port-forwarding } }

Fragmento de código de aplicación de Android:

while (flag) { try { final Socket socket = new ServerSocket(1993).accept(); new AsyncTask<Void, Void, Void>() { @Override public Void doInBackground(Void... params) { while (flag) { try { String line = new BufferedReader(new InputStreamReader(socket.getInputStream())).readLine(); Log.d("", line); } catch (IOException ex) { return null; } } return null; } }.execute(); } catch (IOException ex) { break; } }

Puede convertir su audio a una matriz de bytes y escribirlo en un flujo de salida. Espero que mi respuesta te sea de utilidad.


Voy a comentar tu código pieza por pieza.

private static ServerSocket serverSocket;

No hay razón para que esto sea estático.

while(true) { try { serverSocket = new ServerSocket(port); serverSocket.setSoTimeout(10000);

Las dos últimas líneas deben estar delante del bucle. Esta es la razón de los rechazos de conexión y también causará BindExceptions que no ha mencionado. No está claro por qué necesita el tiempo de espera.

Socket clientSoc = serverSocket.accept(); System.out.println("Waiting for client on port " +serverSocket.getLocalPort() + "...");

No tu no eres Él ya está conectado. Estabas esperando antes de accept().

System.out.println("Just connected to " + clientSoc.getRemoteSocketAddress()); InputStream in = clientSoc.getInputStream(); while(in!=null)

Tanto el bucle como la prueba son inútiles. La variable no es nula inicialmente y no hay forma de que pueda volverse nula. El bucle es inútil porque el método writeToFile() agota completamente el flujo de entrada, por lo que nunca hay nada más que leer. Esto causará datos no deseados, que no has mencionado.

{ writeToFile(in); } System.out.println("socket");

Un mensaje sin sentido.

clientSoc.close();

Todo el código de la línea después de accept() hasta aquí debe ejecutarse en un hilo separado. El bucle de aceptación no debe hacer más que aceptar conexiones e iniciar subprocesos.

}catch(SocketTimeoutException s) { System.out.println("Socket timed out!");

Lo que se agotó el tiempo aquí fue accept() , ya que el conector de escucha es el único conector en el que se estableció un tiempo de espera. Dudo que necesites esto.

break; }catch(IOException e) { e.printStackTrace(); System.out.println("some io");

Otro mensaje inútil.

break; } catch (Exception e) { System.out.println("some e");

Sin embargo, otro más. Cuando obtenga una excepción, imprima la excepción. No es un mensaje inútil de tu propia invención. De lo contrario la depuración se convierte en un mero juego de adivinanzas

e.printStackTrace(); } } } private void writeToFile(InputStream in) throws IOException { // Write the output audio in byte String filePath = "8k16bitMono1.wav"; short sData[] = new short[1024];

No usado. Retirar.

byte[] bData = IOUtils.toByteArray(in);

No uses esto. Se desperdicia espacio y agrega latencia. Vea a continuación la solución correcta.

FileOutputStream os = null; try { os = new FileOutputStream(filePath); } catch (FileNotFoundException e) { e.printStackTrace(); }

Mala técnica. Esta catch está en el lugar equivocado. El código que depende del éxito del código en un bloque try debe estar dentro del mismo bloque try . En este momento, está cayendo en este try-catch como si la excepción nunca hubiera ocurrido, lo que provocará una excepción NullPointerException en el código a continuación.

System.out.println("Short wirting to file" + sData.toString());

Otro mensaje sin sentido. Mal escrito sData no tiene nada en ella; sData.toString() no imprime nada útil independientemente del contenido; e incorrecto, ya que no estás escribiendo sData en absoluto.

try { os.write(bData, 0, 2048);

Esto escribe exactamente 2048 bytes, independientemente de la cantidad leída, que podría ser menor o mayor. Si fuera menos, lanzará una ArrayIndexOutOfBoundsException o similar, que esperaría ver en la segunda llamada, aunque no la haya mencionado, porque la matriz debería ser de longitud cero en la segunda y posteriores llamadas, si las hubiera. Debe ser un bucle, de la forma general:

int count; byte[] buffer = new byte[8192]; // or more if you like while ((count = in.read(buffer)) > 0) { out.write(buffer, 0, count); }

Vuelve a tu código:

} catch (IOException e) { e.printStackTrace(); } try { os.close(); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { // TODO Auto-generated method stub try { Thread serverThread = new auServer(); serverThread.run();

Esto ejecuta el método run() del hilo. No comienza un hilo. Debe ser serverThread.start().

System.out.println("runing");

Mal escrito Hasta que solucione el problema de inicio / ejecución anterior, no verá este mensaje hasta después de que haya salido el método run() del servidor.

y cliente:

private void streamData(byte[] bData) throws UnknownHostException, IOException, InterruptedException { //bData is byte array to transmit Thread.sleep(500);

Inútil. Retirar. No ponga dormidos en el código de red.

Socket client = new Socket("10.221.40.41",3333);

No cree una nueva conexión por búfer. Utilice la misma conexión para la vida del cliente.

OutputStream outToServer = client.getOutputStream(); outToServer.write(bData); if(!isRecording) client.close();

Esto debería ser incondicional, y debería estar en otro lugar, junto con la creación del socket.

¿Cual podría ser el problema?

Problemas. Plural. Múltiple. Véase más arriba.