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.");
    }
}

クライアント サウンドレシーバー クラス: 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);
            }
        }
    }
}

基本的に、すべての着信バイトを 1 つのバイト配列にマージしながら、全員の声をフルに維持したいと考えています (3 方向通話のように)。

4

3 に答える 3

1

new ServerSocket(3000,101); など、serverSocket に制限を設定すると役立つ場合があります。バックログやキューの長さなど..

于 2013-06-11T06:58:59.563 に答える
0

サーバー側でチェックを作成する必要があると思います。sendAll が接続インスタンスを持つ EChoThread から呼び出されている場合、これを sendAll に渡すだけで、sockIt と接続が同じ場合は接続と比較されます。これは、日付を送信しているソケットと同じであり、データを送信する必要はありません。 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 に答える