通过TCP套接字将音频写入服务器

kAm*_*mol 17 java sockets android tcp stream

我正在尝试通过TCP套接字和服务器将实时麦克风录制传输到服务器,以将输入流写入文件.建立连接但是在一段时间后,我在客户端遇到连接拒绝错误.

服务器代码:

    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();
      }
    }
}
Run Code Online (Sandbox Code Playgroud)

和客户:

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();
}
Run Code Online (Sandbox Code Playgroud)

可能是什么问题呢?提前致谢.

use*_*421 15

我将逐件评论你的代码.

private static ServerSocket serverSocket;
Run Code Online (Sandbox Code Playgroud)

这没有理由是静态的.

while(true)
{
    try
    {
        serverSocket = new ServerSocket(port);
        serverSocket.setSoTimeout(10000);
Run Code Online (Sandbox Code Playgroud)

最后两行应该在循环之前.这是连接拒绝的原因,也会导致BindExceptions你没有提到.目前尚不清楚为什么需要超时.

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

不,你不是.他已经联系了.你在等待之前accept().

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

循环和测试都是徒劳的.该变量最初不为null,并且它无法变为null.循环是徒劳的,因为该writeToFile()方法完全耗尽了输入流,因此永远不会有任何东西要阅读.这将导致您没有提到的垃圾数据.

             {
                 writeToFile(in);
             }
             System.out.println("socket");
Run Code Online (Sandbox Code Playgroud)

毫无意义的消息.

             clientSoc.close();
Run Code Online (Sandbox Code Playgroud)

accept()此处到此处的所有代码都应该在一个单独的线程中执行.accept循环除了接受连接和启动线程之外什么都不做.

          }catch(SocketTimeoutException s)
          {
             System.out.println("Socket timed out!");
Run Code Online (Sandbox Code Playgroud)

这里的时间是什么accept(),因为监听套接字是你设置超时的唯一套接字.我怀疑你需要这个.

             break;
          }catch(IOException e)
          {
             e.printStackTrace();
                     System.out.println("some io");
Run Code Online (Sandbox Code Playgroud)

另一个徒劳的信息.

             break;
          } catch (Exception e) {
                    System.out.println("some e");
Run Code Online (Sandbox Code Playgroud)

还有一个.当您收到异常时,请打印异常.不是你自己设计的一些徒劳的信息.否则调试变成一场猜谜游戏.

            e.printStackTrace();
        }
       }
    }

    private void writeToFile(InputStream in) throws IOException {
        // Write the output audio in byte
        String filePath = "8k16bitMono1.wav";
        short sData[] = new short[1024];
Run Code Online (Sandbox Code Playgroud)

没用过.去掉.

        byte[] bData = IOUtils.toByteArray(in);
Run Code Online (Sandbox Code Playgroud)

不要使用它.它浪费空间并增加延迟.请参阅下面的正确解决方案.

        FileOutputStream os = null;
        try {
         os = new FileOutputStream(filePath);
        } catch (FileNotFoundException e) {
         e.printStackTrace();
        }
Run Code Online (Sandbox Code Playgroud)

技术差.这catch是在错误的地方.取决于try块中代码成功的代码应该在同一个try块内.目前你正在堕落try-catch,好像异常从未发生过,这将导致NullPointerException下面的代码.

         System.out.println("Short wirting to file" + sData.toString());
Run Code Online (Sandbox Code Playgroud)

另一个无意义的消息.拼写错误; sData什么都没有; sData.toString()不论内容如何,​​都不会打印任何有用的东西; 并且不正确,因为你根本就不写sData.

         try {
          os.write(bData, 0, 2048);
Run Code Online (Sandbox Code Playgroud)

这写入正好2048字节,无论读取的数量是多少,都可以更少或更多.如果它更小,它会抛出一个ArrayIndexOutOfBoundsException或类似的,我希望在第二次调用时看到,虽然你没有提到它,因为在第二次和后续调用时数组应该是零长度,如果有的话.它应该是一个循环,一般形式:

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

回到你的代码:

         } 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();
Run Code Online (Sandbox Code Playgroud)

这运行run()线程的方法.它不会启动一个线程.它应该是serverThread.start().

        System.out.println("runing");
Run Code Online (Sandbox Code Playgroud)

拼写错误的.在您修复上面的启动/运行问题之前,在服务器run()方法退出之前,您将看不到此消息.

和客户:

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

无意义.去掉.不要把睡眠放入网络代码中.

    Socket client = new Socket("10.221.40.41",3333);
Run Code Online (Sandbox Code Playgroud)

不要为每个缓冲区创建新连接.在客户端的生命周期中使用相同的连接.

    OutputStream outToServer = client.getOutputStream();
    outToServer.write(bData);
    if(!isRecording)
        client.close();
Run Code Online (Sandbox Code Playgroud)

这应该是无条件的,它应该在其他地方,以及套接字的创建.

可能是什么问题呢?

问题.复数.多.往上看.

  • 这就是人们所谓的代码审查 (3认同)
  • @Perroloco是一个很好的人.+ 1为坚实的答案. (2认同)
  • 很好的解释,这是我期待的,一个评论(+1).感谢您的努力,将尝试使用上述指南,如果有效,将标记为答案.再次感谢,抱歉粗鲁:) (2认同)