3

我正在尝试编写一个 Java 语音聊天应用程序,并且已经实现了回声功能,但是在尝试连接多个客户端时,我被卡住了。我知道您不能在不混合数据的情况下遍历套接字并将数据发送给所有连接的人。(我已经尝试过了,这听起来不像它应该的那样)。我不太确定该怎么做,我正在使用一个非常简单的字节缓冲回显服务器作为服务器(我想在其中执行混音)。我还有一个客户端,它接受麦克风输入,将其发送到服务器,从服务器获取数据,然后从扬声器中播放该数据。

注意:客户端由 2 个类(Program 和 SoundReceiver)组成。我正在使用 javax.sound.sampled 库。

回声服务器: http: //pastebin.com/c9KiaTpJ

import java.net.*;
import java.io.*;
import java.util.*;

public class Echo
{
    public static void main(String[] args) throws Exception
    {
        ServerSocket serverSocket = new ServerSocket(3000);
        while(true){Thread echoThread = new Thread(new EchoThread(serverSocket.accept()));
                    echoThread.start();}
    }
}

class EchoThread implements Runnable
{
    public static Collection<Socket> sockets = new ArrayList<Socket>();
    Socket connection = null;
    DataInputStream dataIn = null;
    DataOutputStream dataOut = null;

    public EchoThread(Socket conn) throws Exception
    {
        connection = conn;
        dataIn = new DataInputStream(connection.getInputStream());
        dataOut = new DataOutputStream(connection.getOutputStream());
        sockets.add(connection);
    }

    public void run()
    {
        int bytesRead = 0;
        byte[] inBytes = new byte[1];
        while(bytesRead != -1)
        {
            try{bytesRead = dataIn.read(inBytes, 0, inBytes.length);}catch (IOException e){}
            if(bytesRead >= 0)
            {
                sendToAll(inBytes, bytesRead);
            }
        }
        sockets.remove(connection);
    }

    public static void sendToAll(byte[] byteArray, int q)
    {
        Iterator<Socket> sockIt = sockets.iterator();
        while(sockIt.hasNext())
        {
            Socket temp = sockIt.next();
            DataOutputStream tempOut = null;
            try
            {
                tempOut = new DataOutputStream(temp.getOutputStream());
            } catch (IOException e1)
            {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            try{tempOut.write(byteArray, 0, q);}catch (IOException e){}
        }
    }
}

客户端程序类: http: //pastebin.com/v24CYwXE

import java.io.DataOutputStream;
import java.net.*;
import javax.sound.sampled.*;

public class Program
{
    public static void main(String[] args) throws Exception
    {
        AudioFormat af = new AudioFormat(8000.0f,8,1,true,false);
        DataLine.Info info = new DataLine.Info(TargetDataLine.class, af);
        TargetDataLine microphone = (TargetDataLine)AudioSystem.getLine(info);
        microphone.open(af);
        Socket conn = new Socket("localhost",3000);
        microphone.start();
        DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
        int bytesRead = 0;
        byte[] soundData = new byte[1];
        Thread inThread = new Thread(new SoundReceiver(conn));
        inThread.start();
        while(bytesRead != -1)
        {
            bytesRead = microphone.read(soundData, 0, soundData.length);
            if(bytesRead >= 0)
            {
                dos.write(soundData, 0, bytesRead);
            }
        }
        System.out.println("IT IS DONE.");
    }
}

客户端 SoundReceiver 类: http: //pastebin.com/2tt0Jucv

import java.net.*;
import java.io.*;

import javax.sound.sampled.*;

public class SoundReceiver implements Runnable
{
    Socket connection = null;
    DataInputStream soundIn = null;
    SourceDataLine inSpeaker = null;

    public SoundReceiver(Socket conn) throws Exception
    {
        connection = conn;
        soundIn = new DataInputStream(connection.getInputStream());
        AudioFormat af = new AudioFormat(8000.0f,8,1,true,false);
        DataLine.Info info = new DataLine.Info(SourceDataLine.class, af);
        inSpeaker = (SourceDataLine)AudioSystem.getLine(info);
        inSpeaker.open(af);
    }

    public void run()
    {
        int bytesRead = 0;
        byte[] inSound = new byte[1];
        inSpeaker.start();
        while(bytesRead != -1)
        {
            try{bytesRead = soundIn.read(inSound, 0, inSound.length);} catch (Exception e){}
            if(bytesRead >= 0)
            {
                inSpeaker.write(inSound, 0, bytesRead);
            }
        }
    }
}

基本上,我想将所有传入字节合并到一个字节数组中,同时保持每个人的声音都是完整的(就像一个 3 路电话一样)。

4

3 回答 3

1

设置 serverSocket 的限制可能会有所帮助,例如 new ServerSocket(3000,101); 诸如积压或队列长度之类的东西..

于 2013-06-11T06:58:59.563 回答
1

就是这一行:

try
{
    tempOut.write(byteArray, 0, q);
}
catch (IOException e){
} 

在服务器端,我认为将数据发送回客户端,因为有回声。我认为您应该省略该行。

于 2014-01-15T13:40:25.470 回答
0

我认为您需要在服务器端创建一个检查。就像从具有连接实例的 EChoThread 调用 sendAll 一样,只需将其传递给 sendAll 并将 sockIt 与 connection 进行比较,如果它们相同,那么这是发送日期的同一个套接字,无需向其发送数据self 所以跳过它并移动到下一个套接字。

应在服务器端进行以下更改:

     public void run()
{
    int bytesRead = 0;
    byte[] inBytes = new byte[1];
    while(bytesRead != -1)
    {
        try{bytesRead = dataIn.read(inBytes, 0, inBytes.length);}catch (IOException e)       {}
        if(bytesRead >= 0)
        {
            sendToAll(connection, inBytes, bytesRead);
        }
    }
    sockets.remove(connection);
}


public static void sendToAll(Socket connection, byte[] byteArray, int q)
{
    Iterator<socket> sockIt = sockets.iterator();
    while(sockIt.hasNext())
    {
        Socket temp = sockIt.next();
        if(connection == temp){
            continue;
        }
        DataOutputStream tempOut = null;
        try
        {
            tempOut = new DataOutputStream(temp.getOutputStream());
        } catch (IOException e1)
        {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        try{tempOut.write(byteArray, 0, q);}catch (IOException e){}
      }
  }




 public void run()
{
    int bytesRead = 0;
    byte[] inBytes = new byte[1];
    while(bytesRead != -1)
    {
        try{bytesRead = dataIn.read(inBytes, 0, inBytes.length);}catch (IOException e)       {}
        if(bytesRead >= 0)
        {
            sendToAll(connection, inBytes, bytesRead);
        }
    }
    sockets.remove(connection);
}


public static void sendToAll(Socket connection, byte[] byteArray, int q)
{
    Iterator<socket> sockIt = sockets.iterator();
    while(sockIt.hasNext())
    {
        Socket temp = sockIt.next();
        if(connection == temp){
            continue;
        }
        DataOutputStream tempOut = null;
        try
        {
            tempOut = new DataOutputStream(temp.getOutputStream());
        } catch (IOException e1)
        {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        try{tempOut.write(byteArray, 0, q);}catch (IOException e){}
      }
  }
于 2014-01-17T05:16:51.947 回答