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


Escritura de audio en el servidor a través de un socket TCP

Estoy intentando transmitir la grabación en tiempo real del micrófono al servidor sobre el zócalo del TCP y al servidor para escribir la corriente de la entrada a un archivo. La conexión se establece pero después de algún tiempo, estoy recibiendo error de conexión rechazado en mi clientside.

Código del servidor:

  • Color Estado Lista no reconocida en forma Drawable
  • Cómo probar la aparición de un mensaje Toast
  • Error al ejecutar 'play' en 'HTMLMediaElement': la API sólo puede iniciarse con un gesto del usuario
  • ¿Por qué usar WeakReference en los oyentes de Android?
  • Color negro androide a 85% de opacidad
  • Guardar / Crear MMS en la bandeja de entrada de Android
  • 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.

  • Transmisión de voz entre teléfonos Android con WiFi
  • Transmisión al MediaPlayer de Android
  • Mime-tipos disponibles para Android?
  • ¿Cómo agregar un tipo de mime personalizado?
  • ¿Cómo comprobar si el paquete existe desde dentro del procesador de anotación (en tiempo de compilación)?
  • Error al llamar a Appregistry.runApplication en reactivo-nativo
  • 4 Solutions collect form web for “Escritura de audio en el servidor a través de un socket TCP”

    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 las denegaciones de conexión, y también causará BindExceptions que no has 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, no lo eres. 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 inicialmente nula, y no hay manera de que pueda llegar a ser 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 basura, que no ha mencionado.

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

    Un mensaje inútil.

      clientSoc.close(); 

    Todo el código de la línea después de accept() a aquí debe ejecutarse en un hilo separado. El bucle de aceptación no debe hacer nada más que aceptar conexiones y comenzar hilos.

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

    Lo que terminó aquí fue accept() , ya que el socket de escucha es el único socket en el que ha establecido 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"); 

    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 lo uses. Perjudica el espacio y añade 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 la actualidad está cayendo a través de este try-catch como si la excepción nunca sucedió, lo que causará una NullPointerException en el código de abajo.

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

    Otro mensaje inútil. Misspelt; sData no tiene nada en él; sData.toString() no imprime nada útil independientemente del contenido; sData incorrecto, ya que no está 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 más. Si fuera menos arrojará una ArrayIndexOutOfBoundsException o similar, que esperaría ver en la segunda llamada, aunque no la haya mencionado, ya que la matriz debe ser de longitud cero en la segunda y las siguientes llamadas, si las hay. 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); } 

    Volver al 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 subproceso. No inicia un hilo. Debe ser serverThread.start().

      System.out.println("runing"); 

    Señorita Hasta que no corrija el problema de inicio / ejecución anterior, no verá este mensaje hasta que el método run() del servidor haya salido.

    Y Cliente:

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

    Inútil. Retirar. No coloque duerme 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 debe ser incondicional, y debe estar en otra parte, junto con la creación de la toma.

    ¿Cual podría ser el problema?

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

    La creación del socket de servidores debe realizarse fuera del bucle. Y para las conexiones paralelas que necesita para iniciar un hilo por conexión.

    También aplique 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 nada que usted quiere 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(); } } } ... 

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

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

    Aquí viene el verdadero negocio!

    Antes de empezar a ejecutar aplicaciones, debe ejecutar el siguiente comando en shell de adb (o puede localizar 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 android y verso sabio, utilizando las secuencias de E / S de los sockets.

    Extracto 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 en matriz de bytes y escribirlo en una secuencia de salida. Espero que mi respuesta sea útil.

    Me imaginé la solución. El problema fue en realidad con el bloqueo de E / S de red debido a flujo mal codificado.

    Lo que extrañé 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); 
    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.