1

マルチスレッド中にブロードキャスト データを読み取るためのストリーミング データ キャプチャで 1 つの問題に直面しています。

実際には、udp ソケットの 1 つからデータを読み取るクラスが 1 つあります。別のクラスは、すべてのクライアント要求から tcp 接続を受け入れ、すべてのクライアントに対してスレッドを作成し、データに対して同じ udp クラスを要求します。作成された最初のスレッドで作業しています。しかし、別の pc/ip から別のクライアントで要求すると、パケットは 2 番目のクライアント/スレッドに失われます

Threads outputstream オブジェクトを格納するリストを作成し、それをループしてデータをすべてのクライアントに送信することで、回避策を作成しました。ただし、クライアント/接続が増加するとパケットが遅延するため、これは一時的なものです。

UDP データを読み取るためのコード

   public class EventNotifier    
    {
      private InterestingEvent ie;
      public DatagramSocket clientSocket;
      public String[] split_str;

      byte[] receiveData;

      HashMap<String, String> secMap = new HashMap<String, String>();


      public EventNotifier(InterestingEvent event)
      {
        ie = event; 
     clientSocket = new DatagramSocket(9050);
        receiveData = new byte[500];
      }



      public String getDataFeed(String client_id)
      {
        try 
        {
             DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
             clientSocket.receive(receivePacket);
             String s = new String(receivePacket.getData());
             String split_str = s.split(","); 
             if(secMap.containsValue(split_str[0]))
                  return s;
             else
                  return "";
             } catch(Exception e3) {}
      }
     }// end of eventNotifier class

クライアント要求を処理するマルチスレッドのコード

public class multiServer 
{

    static protected List<PrintWriter> writers = new ArrayList<PrintWriter>();
    static String client_id = "";
    public static void main(String[] args)
    { 
       try
       {
           ServerSocket servsock = new ServerSocket(8858);
           Socket incoming;
           while(true)
           {
             incoming = servsock.accept();
             multiServerThread  connection = new multiServerThread(incoming);

             Thread t1 = new Thread(connection);
             t1.start();
           }
       }
       catch(IOException e)
       {
            System.out.println("couldnt make socket");
       }
    }
}

class multiServerThread extends Thread implements InterestingEvent
{

    Socket incoming;
    PrintWriter out=null;
    PrintWriter broad=null;
    BufferedReader in = null;
    String cliString=null;
    private EventNotifier en; 
    int id;

    public static String udp_data;

    public void interestingEvent(String str1)
    {
          this.udp_data = str1;
    }
    public String getUdpData()
    {
      String _udp_data = this.udp_data;
      return _udp_data;
    }
    multiServerThread(Socket incoming)
    {  
        this.incoming=incoming;
        en = new EventNotifier(this);
    } 
    public void run()
    {
        try
        {
            out = new PrintWriter(incoming.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(incoming.getInputStream()));
        cliString = in.readLine();
        multiServer.writers.add(out);
        while(true)
                {
               try
                   {
                    udp_data = en.getDataFeed(cliString);
                    if(udp_data!=null && udp_data.length()>0)
                    {
              //workaround for serving the data to all cleints who are connected    
                        for (int i=0; i<multiServer.writers.size();i++)
                        {
                            broad=multiServer.writers.get(i);
                            broad.println(udp_data.trim());
                        }
             //else will directly write to the outputstream object for every thread which is connected
             // out.println(udp_data.trim());
                    }

               }
               catch (Exception e)
               {
                 System.out.println("exception "+e);
               }
               Thread.sleep(1);

            }
        } catch(IOException e)
        {
            System.out.print("IO Exception :: "+ e);
        }
        catch(InterruptedException e)
        {
            System.out.print("exception "+ e);
        }        
    }
}
4

1 に答える 1

0

相互排除 (または別の設計) が必要です。

たとえば、2 つのスレッドがmultiServer.writers.add(out); 同時に呼び出すとどうなるでしょうか。

ArrayList Javadoc から

この実装は同期されていないことに注意してください。複数のスレッドが ArrayList インスタンスに同時にアクセスし、少なくとも 1 つのスレッドがリストを構造的に変更する場合は、外部で同期する必要があります。(構造変更とは、1 つ以上の要素を追加または削除する操作、または [...])

もう 1 つの問題は、2 つのudp_data = en.getDataFeed(cliString);同時呼び出しです。2 番目のスレッドが最初のスレッドの結果を上書きする可能性があります。データが失われます。

for (int i=0; i<multiServer.writers.size();i++)あるスレッドがビジー状態で別のスレッドを呼び出すとどうなりmultiServer.writers.add(out);ますか? outが実際にリストに追加される前に、サイズが大きくなった可能性があります。

public class multiServer 
{

    private List<PrintWriter> writers = new ArrayList<PrintWriter>();

    public synchronized void addWriter(PrintWrite out) {
         writers.add(out);
    }
    public synchronized void serveAllWriters(String data) {
         for (int i=0; i<multiServer.writers.size();i++)
         {
             broad=multiServer.writers.get(i);
             broad.println(data);
         }
    }
}

スレッドがライターを追加しようとすると、synchronizeds は他のスレッドが実行中addまたは印刷中でないことを確認します。したがってmultiServerThread、新しいメソッドを使用するように修正する必要があります。

class multiServerThread extends Thread implements InterestingEvent
{
      //...
      private String udp_data;
      //...
      myMultiServer.addWriter(out);

      //...
      udp_data = en.getDataFeed(cliString);
      if(udp_data!=null && udp_data.length()>0)
            myMultiServer.serveAllWriters(udp_data.trim());
      //...
}

あなたのコードを完全には理解していないので、もっと問題があるかもしれません。自問しなければならない質問は、別のスレッドが同じデータまたはオブジェクトを読み書きできるかということです。はい?次に、適切な同期が必要になります。

于 2012-06-25T08:19:04.490 に答える