JAVA(在同一台机器上发送音频流一台服务器四台客户端)

时间:2016-02-18 20:32:47

标签: java multithreading audio tcp client-server

我之前问过:https://stackoverflow.com/questions/35344535/dcom-alternative-for-java-sending-audio-streaming-in-the-same-machine

我想从我的麦克风中捕获音频并使用One Server发送给客户端(0或4)...

PD:我正在检查这个问题:Sending audio stream over TCP, UnsupportedAudioFileException但面向的是一台具有One Client解决方案的服务器。 其他问题:Java - Broadcast voice over Java sockets Streaming audio from microphone with Java

我正在考虑使用TCP(服务器/客户端模型),但服务器和4个客户端将接收数据(音频流)并且我不知道是否可以实现此替代方案(I&#39 ; m担心港口管理)....

这是我的初步(它仍然不起作用,因为我怀疑并且我在思考如何解决我的诅咒)

变量:

static boolean bThreadCapture = false;
static boolean bThreadServer = false;
static ByteArrayOutputStream myByteArrayOutStream;
ExecutorService myServerPool = Executors.newFixedThreadPool(4);
static Thread myThreadServer = null;

现在我的头痛

  final int iServerPort = 2370;
  final AudioFormat myAudioFormat = new AudioFormat(8000,8,1,false, true);
  final DataLine.Info myDataLineInfo = new DataLine.Info(TargetDataLine.class, myAudioFormat);
  if (!AudioSystem.isLineSupported(myDataLineInfo)) {
    System.out.println("Line not supported");
    System.exit(0);
  }
  try {
    final TargetDataLine myTargetDataLine = (TargetDataLine) AudioSystem.getLine(myDataLineInfo);
    myTargetDataLine.open(myAudioFormat);
    myByteArrayOutStream = null;

    //BEGIN definition Thread for CAPTURING AUDIO FROM MIC
    Runnable runnAudioCapture = new Runnable() {
      int bufferSize = (int) myAudioFormat.getSampleRate()* myAudioFormat.getFrameSize();
      byte buffer[] = new byte[bufferSize];
      public void run() {
        myByteArrayOutStream = new ByteArrayOutputStream();
        bThreadCapture = true;
        while (bThreadCapture) {
          try {
            int count = myTargetDataLine.read(buffer, 0, buffer.length);
            if (count > 0) {
              myByteArrayOutStream.write(buffer, 0, count);
              //  HERE: I need to send the bytes of Sound to all active Threads Client (from 1 until 4)
              //  But, How to know what (how much and which) are active threads client?
              //  How to access to each Executor?
            }
          } catch (IllegalArgumentException | ArrayIndexOutOfBoundsException e) {
            System.err.println("TargetDataLine problems: " + e);
          }
        }
        try {
          if (myByteArrayOutStream != null) myByteArrayOutStream.close();
        } catch (IOException e) {  }
      }
    };
    //END definition Thread for CAPTURING AUDIO FROM MIC


    //BEGIN definition Thread for ATTENDANT SERVER CLIENT (Still not defined) 
    myThreadServer = new Thread() {
      @Override
      public void run() {
        try {
          SrvrSocketProducer = new ServerSocket(iServerPort);
          System.out.println("Server Listening on port number: "+iServerPort);
        } catch (IOException e) {
          System.out.println("Could not listen on port: "+iServerPort);
        }
        new Thread(runnAudioCapture).start();  //BEGIN AUDIO CAPTURE
        while(bThreadServer) {
          Socket clientSocket = null;
          try {
            clientSocket = SrvrSocketProducer.accept(); 
          } catch (IOException e) {
            if(!bThreadServer) {
              System.out.println("Server Stopped.") ;
              break;
            }
            throw new RuntimeException("Error accepting client connection", e);
          }
          myServerPool.execute(new runnWorkerListener(clientSocket,myAudioFormat));
        }
        myServerPool.shutdown();
        bThreadCapture = false;  //STOP AUDIO CAPTURE
      }
    };
    //END definition Thread for ATTENDANT SERVER CLIENT (Still not defined) 
    myThreadServer.start();
  } catch (LineUnavailableException ex) {
    System.out.println(ex.toString());
  }

问题:

(在runnAudioCapture代码中合并以找到帮助)

1. HERE: I need to send the bytes of Sound to all ACTIVE Threads Client (from 1 until 4)
2. But, How to know what (how much and which) are active threads client?
3. How to access to each Executor?

现在工作线程 -

  class runnWorkerListener implements Runnable {
    Socket innerClientSocket = null;
    AudioFormat innerAdfmt = null;
    public runnWorkerListener(Socket clientSocket, AudioFormat audioFormat) {
      innerClientSocket = clientSocket;
      innerAdfmt = audioFormat;
    }
    public void run() {
      try {
        InputStream input  = innerClientSocket.getInputStream();
        OutputStream output = innerClientSocket.getOutputStream();
        // Now How Can I to Comunicate with runnAudioCapture?
        while (RunningClientAttender /*This variable still is not defined*/) {
          // I need to send (thread client here Not defined) EACH bytes from runnAudioCapture
        }
        output.close();
        input.close();
        System.out.println("Request processed: ");
      } catch (IOException e) {
        //report exception somewhere.
        e.printStackTrace();
      }
    }
  }

问题:

(在runnWorkerListener代码中合并以查找帮助)

1. Now How Can I to Comunicate with runnAudioCapture?
2. I need to send (thread client here Not defined) EACH bytes from runnAudioCapture

我怀疑与以下事项有关: 一个致力于音频捕获的线程 一个线程专用于使用Pool接收客户端(1,2,3或4)并创建线程工作者(一个线程工作者与#34;远程"客户端进行通信)

我不知道处理器将Capturer线程Capturer与每个工作线程同步...

谢谢...

1 个答案:

答案 0 :(得分:0)

不幸的是,在Java中,流只能由一个人一次使用。您有一个流myByteArrayOutStream,并且您希望在4个TCP连接之间共享它。

我建议您将音频数据写入文件。每次客户端连接时,您都会将文件的所有内容流式传输到该客户端(您可以打开文件,跳到最后,如果需要,只传输新内容)。您需要为每个客户端创建一个新线程。

如果您希望在Java中构建类似Skype音频的东西,那么这比使用TCP要复杂一些。 TCP是一种从A到B,可靠地获取数据的方法。对于音频,您通常希望它从A到B,但实时。如果您在此过程中丢失了一个数据包,则不希望返回并重新传输它,因为这会导致呼叫延迟。 TCP的替代方案,可能更适合您的方案,是UDP。它发送单个数据包,并不保证它们按顺序到达,甚至根本不到。但它并没有停止并等待丢失的数据包。