2010-12-03 15 views
1

Java Datagramsを使用してサーバーとクライアントの間にパケットストリームを作成しようとしています。問題は、パケットが送信されているという確認を受け取ったにもかかわらず、設定したクライアントリスナにパケットが届く前にパケットが失われていることです。私は今すぐ持っているので、5秒後にタイムアウトが発生します。これは実行するたびに発生します。Java Datagramソケットがパケットを受信しない

class DGServer extends Thread 
{ 
    private DatagramSocket server; 

    public DGServer() throws IOException 
    { 
     server = new DatagramSocket(); 
    } 

    public void run() 
    { 
     try 
     { 
      server.connect(App.Local, 4200); 
      System.out.println("Server starting..."); 

      int i = 0; 

      while (server.isConnected() && (i < 256)) 
      { 
       byte[] buffer = new byte[1]; 
       buffer[0] = (byte) ++i; 
       DatagramPacket packet = new DatagramPacket(buffer, buffer.length, App.Local, 4200); 
       System.out.println("Sedning " + i + " to client..."); 

       server.send(packet); 

       Thread.sleep(500); 
      } 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
     } 
     System.out.println("Server Finished!"); 

     if (! server.isClosed()) 
      server.close(); 
    } 

} 

class DGClient extends Thread 
{ 
    private DatagramSocket client; 

    public DGClient() throws SocketException 
    { 
     client = new DatagramSocket(); 
    } 

    public void run() 
    { 
     try 
     { 
      client.connect(App.Local, 4200); 
      client.setSoTimeout(5000); 
      System.out.println("Client starting..."); 

      int i = 0; 

      while (client.isConnected() && (i < 256)) 
      { 
       byte[] buffer = new byte[1]; 
       DatagramPacket packet; 
       packet = new DatagramPacket(buffer, 1, App.Local, 4200); 
       //System.out.println("Sedning " + i + " to server..."); 

       client.receive(packet); 

       buffer = packet.getData();   
       System.out.println("Client Received:\t" + packet.getData()[0]); 

       Thread.sleep(500); 
      } 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
     } 
     System.out.println("Client Finished!"); 

     if (! client.isClosed()) 
      client.close(); 
    } 

} 

2番目のクラスをスキムオーバーすることもできます。それらは広く同じで、単にserver.sendをclient.receiveに置き換えます。また、このクラスは本当に重要なことをするようには設計されていませんでした。だから、多くのコード(Exception handlingなど)は非常に単純化されて書かれています。

パケットの損失を防ぐためにできることはありますか?私はポートを自分のコンピュータに転送しました(それは問題ではありません、私はlocalhostを使用しています、あなたが疑問に思った場合にはApp.Localです)。

また、サイド質問です。私はもともとそれが単一のクラスとして設定されていて、パケットを送信するようにコード化されていて、振り返って受信しました。しかし、「ICMPポートに到達できないため」例外がスローされました。誰がなぜこれが起こるのか知っていますか?

+0

どのようにそれらが失われていることを知っていますか? wiresharkのようなパケットトレーサを設定して、どこに行くのか見てみましたか? – javamonkey79

答えて

1

なぜサーバーとクライアントの両方が接続していますか? データを送信してはいけませんか?以下のような

何かが:あなたが使用しているポート上のクライアントとサーバ間のUDPトラフィックに干渉し、いくつかのパケットフィルタ/ファイアウォールがあるよう

 

DatagramSocket socket = new DatagramSocket(); 

DatagramPacket packet = new DatagramPacket(buf, buf.length, 
              address, 4200); 
socket.send(packet); 
 
1

それは私に聞こえます。単純なパケットフィルタリング、NAT(特別な手順を取らない限りUDPトラフィックを妨害する)、それが偶発的なネットワーク誤設定の可能性があります。

しかし、 'ICMPポートに到達できないため'例外がスローされました。誰がなぜこれが起こるのか知っていますか?

IMO、これはパケットフィルタリングの証拠です。

(ただし、データグラムを送信しようとしたときにこれを受け取るべきではないという予期しないこともあります。私は単純に応答がないことを期待しています。あなたは、通常のストリームソケットを使用していた場合、私は今...

このことについて間違っている可能性があり、OSによって床に落とししかし、。例えばTCP/IPは、この動作が理解できるだろう)

+0

これは次のような文脈にあります。 client.send(パケット); client.receive(パケット);それは実際に受信ラインにあった。 – B3tturTh3nU

+0

おそらく、OSが予想外のICMPトラフィックをUDPデータグラムソケットに送り返していて、 'receive'を実行したときに例外になっている可能性があります。いずれにせよ、これはパケットフィルタリングの証拠です。 –

4

[OK]をクリックします。まず、サーバーとクライアントの両方を同時にテストしていると思いますので、どのサーバーが失敗するかわからないと思います。あなたはnetcatを使ってクライアント

をテストするためのnetcat(NC)またはwiresharkのいずれかを使用する必要があります

、あなたはこれは、UDP上(-l)を聞くためのnetcatを教えてくれます

nc -l -u -p 4200 -vv 

次のコマンドを実行することができます(-u)をポート(-p 4200)に設定し、非常に冗長にする(-vv)

この方法で、クライアントが何かに接続できるかどうかを確認できます。

サーバーが

nc -u [target ip] 4200 

There is a netcat cheatsheet here

それが純粋である場合にも、診断するのnetcatへのnetcatを確認することができますと正常に動作しているプログラムからの接続を受信できるかどうかをチェックするために、同じプログラムを使用することができます

ネットワークの問題。ファイアウォール/ NATが正しく設定されていない可能性があります

1

送信ソケットを特定のポート番号にバインドしていないため、接続されているクライアントは送信できません。あなたは逆問題でも同じ問題があると思っています。つまり、クライアントソケットはポート4200にバインドされていません。

私は接続を取り除き、明示的なポート番号を使用して送信し、受信ポート番号を使用して応答します。

0

あなたは、UDPがロッシーなプロトコルであり、これを許可していることを認識していると確信しています。まだいくつかのパケットを取得する必要があります。

ファイアウォールを避けて、同じホスト上と異なるホスト上でクライアントとサーバーを使用してプログラムが動作するかどうかをテストすることをお勧めします。これが機能する場合は、ネットワーク構成の問題があります。

1

両方を同じマシンで実行している場合、両方を(サーバーとクライアント)を同じポートに接続しているため、これはうまくいかないでしょう。