【问题标题】:Stream Audio from Client to Server to Multiple Clients Java将音频从客户端流式传输到服务器到多个客户端 Java
【发布时间】:2015-01-18 11:22:38
【问题描述】:

正如标题所示,我正在制作一个应用程序,将音频从客户端流式传输到存储音频的服务器,然后将其分发到多个客户端进行播放。在音频存储之前,我已经完成了所有工作,但我似乎无法将音频流式传输到多个客户端。

这是我的尝试:

服务器代码:

class Server {

    static int port = 50005;
    static int listen = 50010;
    static int listenerPort = 50015;
    static DatagramSocket serverSocket, listenSocket,
                            broadcastSocket;
    static byte[] receiveData, listenData;
    static DatagramPacket receivePacket, listenPacket;
    static DataOutputStream out;
    static ArrayList<String> listeners = new ArrayList<String>();
    static File file = new File("recording.bin");
    static boolean active = true;


    public static void main(String args[]) throws Exception {
        //Define the Receiving Datagram Socket
        serverSocket = new DatagramSocket(port);
        //Define the Timeout of the socket
        serverSocket.setSoTimeout(10000);
        //Define the listening socket
        listenSocket = new DatagramSocket(listen);
        listenSocket.setSoTimeout(10000);
        //Define Broadcasting socket
        broadcastSocket = new DatagramSocket();

        //Define data size, 1400 is best sound rate so far
        receiveData = new byte[1400];
        listenData = new byte[256];

        //Define the DatagramPacket object
        receivePacket = new DatagramPacket(receiveData, receiveData.length);
        listenPacket = new DatagramPacket(listenData, listenData.length);

        //Prepare the DataOutputStream to write to file.
        out = new DataOutputStream(new FileOutputStream(file));
        //Write and Broadcast on a separate thread
        Thread t = new Thread() {
            @Override public void run() {
                getPackets();
            }
        };
        t.start();
        //Set up Connection Listener on a separate thread
        Thread l = new Thread() {
            @Override public void run() {
                listen();
            }
        };
        l.start();
    }

    /***
     * Function that gets the audio data packets
     * saves them, and outputs the audio to the speakers.
     */
    public static void getPackets() {
        while (active) {
            try {
                //Wait until packet is received
                serverSocket.receive(receivePacket);
                System.out.println("Receiving Data");
                //Write to Binary file
                out.write(receiveData, 0, receiveData.length);
                //Send data
                sendData(receivePacket.getData());
            } catch (IOException e) {
                active = false;
                //If connection times out close it
                try {
                    out.close();
                } catch (IOException t) {
                    //Do nothing
                }
                System.out.println("Converting to audio");
                //Convert audio file
                new Convert().toWAV();
            }
        }
    }

    /***
     * Function that listens if there are any connections made to
     * the listener port and creates a datagram socket to stream audio
     * to anyone who connects
     */
    public static void listen() {
        while (active) {
            try {
                //Wait until packet is received
                listenSocket.receive(listenPacket);
                listeners.add(listenPacket.getAddress().getHostAddress());
                System.out.println("Client received");

            } catch (IOException e) {
                if(active) {
                    listen();
                }
            }
        }
    }

    public static void sendData(byte[] data) {
        try {
            for (int i = 0; i < listeners.size(); i++) {
                InetAddress destination = InetAddress.getByName(listeners.get(i));
                broadcastSocket.send(new DatagramPacket(data, data.length, destination, listenerPort));
                System.out.println("Sending Data");
            }
        } catch (Exception e) {
            //If it failed to send don't do anything
            e.printStackTrace();
        }
    }
}

这是我在多个客户端上运行的代码:

class Receiver {

    static AudioInputStream ais;
    static AudioFormat format;
    static boolean active = true;
    static int port = 50015;
    static DatagramSocket serverSocket, socket;
    static byte[] receiveData;
    static DatagramPacket receivePacket, packet;
    static ByteArrayInputStream bais;
    static int sampleRate = 8000;
    static int time = 10;

    static DataLine.Info dataLineInfo;
    static SourceDataLine sourceDataLine;

    public static void main(String args[]) throws Exception {
        socket = new DatagramSocket();
        InetAddress destination = InetAddress.getByName("server ip address");
        byte[] temp = new byte[256];
        //putting buffer in the packet
        packet = new DatagramPacket(temp, temp.length, destination, 50010);

        socket.send(packet);

        //Define the Receiving Datagram Socket
        serverSocket = new DatagramSocket(port);

        //Define data size, 1400 is best sound rate so far
        receiveData = new byte[1400];
        //Define the format sampleRate, Sample Size in Bits, Channels (Mono), Signed, Big Endian
        format = new AudioFormat(sampleRate, 16, 1, true, false);
        //Define the DatagramPacket object
        receivePacket = new DatagramPacket(receiveData, receiveData.length);
        //Prepare the Byte Array Input Stream
        bais = new ByteArrayInputStream(receivePacket.getData());
        //Now concert the Byte Array into an Audio Input Stream
        ais = new AudioInputStream(bais, format, receivePacket.getLength());

        //Define DataLineInfo
        dataLineInfo = new DataLine.Info(SourceDataLine.class, format);
        //Get the current Audio Line from the system
        sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
        //Open up sourceDataLine and Start it
        sourceDataLine.open(format);
        sourceDataLine.start();

        //Write and play on a separate thread
        Thread t = new Thread() {
            @Override
            public void run() {
                getPackets();
            }
        };
        t.start();
        //Now keep track of time
        while (time > 0) {
            time--;
            Thread.sleep(1000);
            if (time == 0) {
                active = false;
            }
        }
        //Close SourceDataLine
        sourceDataLine.drain();
        sourceDataLine.close();
    }

    /***
     * Function that gets the audio data packets
     * saves them, and outputs the audio to the speakers.
     */
    public static void getPackets() {
        try {
            while (active) {
                System.out.println("Receiving");
                //Wait until packet is received
                serverSocket.receive(receivePacket);
                //Reset time
                time = 10;
                //Send data to speakers
                toSpeaker(receivePacket.getData());
            }
        } catch (IOException e) {
        }
    }

    /***
     * Function that plays the sound bytes with the speakers.
     * @param soundbytes = bytes of sound sent to speakers
     */
    public static void toSpeaker(byte soundbytes[]) {
        try {
            sourceDataLine.write(soundbytes, 0, soundbytes.length);
        } catch (Exception e) {
            System.out.println("Not working in speakers...");
            e.printStackTrace();
        }
    }
}

我已验证服务器确实收到了我用来获取客户端 IP 地址的初始连接,但客户端似乎没有收到任何数据,并且我在运行时没有收到任何错误。

任何帮助将不胜感激。

【问题讨论】:

    标签: java android audio streaming


    【解决方案1】:

    好吧,在搞砸了一段时间后,我意识到问题不在于代码,而在于建筑物网络的管理员阻止了我。因此,我将继续并将其标记为已回答。

    【讨论】:

    • 我需要你帮我一个忙。请您与我们分享您使用 50005 端口(或客户端捕获音频并发送到服务器类的 serverSocket)的客户端发送器代码吗?提前致谢。
    • 自从发布此代码以来,我已对该代码进行了多次更改,但它看起来不再像这样了,如果您将此代码用于您自己的项目,那么您所要做的就是向它发送音频的方法是在客户端启动一个数据报套接字,然后制作一个数据报包并包含音频字节、服务器的 IP 地址和端口(50005),然后通过数据报套接字发送数据报包,就是这样.
    • 您能告诉我们您的新解决方案怎么样?我必须做同样的事情。
    • 我当前的解决方案仍然使用其中的一些代码。真正的区别在于我为它添加了更多功能并且结构更好。我在其中添加的一些未来:NAT 检测、UDP 冲孔和 TCP 连接作为后备。还添加了对 Web 套接字的支持,因此它也可以实时流式传输到浏览器。可能会使其开源,但需要从中提取一些东西,但目前没有时间处理它。
    猜你喜欢
    • 2014-01-19
    • 2020-11-16
    • 1970-01-01
    • 2010-10-17
    • 2012-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多