2012-01-23 9 views
3

私は本当に奇妙な問題に遭遇して、UDPソケットを使用してJavaで本当に基本的なサーバ - クライアントモデルを実装しています。Java UDPソケット - データはサーバ側で残されています

私がしたいのは、ユーザー(クライアント)がサーバーにメッセージを送信し、サーバーがそれを印刷することだけです。

私は例があるが、私は以下の問題があるので、私は何かが欠けています:クライアントは「」それが正しく受信されますサーバーにメッセージを送信した場合

を。 クライアントが "bbb"というメッセージをサーバーに送信すると、正しく受信されます。 クライアントが "c"というメッセージをサーバーに送信すると、サーバーは "cbb"を受信メッセージとして出力します。

サーバーが新しいメッセージを受け取ったときに、何らかの種類のバッファをクリーンアップしているようです。

これは私が使用していたコードです:

サーバー

import java.net.DatagramPacket; 
import java.net.DatagramSocket; 
import java.net.InetAddress; 



public class UDPServer { 
public static void main(String args[]) throws Exception { 
    byte[] receive_data = new byte[256]; 
    int recv_port; 

    DatagramSocket server_socket = new DatagramSocket(5000); 

    System.out.println("Server - Initialized server. Waiting for client on port 5000"); 

    while (true) { 
     // System.out.println("Server - Listening for connections..."); 
     DatagramPacket receive_packet = new DatagramPacket(receive_data, receive_data.length); 

     server_socket.receive(receive_packet); 

     String data = new String(receive_packet.getData()); 

     InetAddress IPAddress = receive_packet.getAddress(); 

     recv_port = receive_packet.getPort(); 

     if (data.equals("q") || data.equals("Q")) { 
      System.out.println("Server - Exiting !"); 
      break; 
     } else { 
      System.out.println("Server - Client from IP " + IPAddress + " @ port " + recv_port + " said : " + data + " (length: " + receive_packet.getLength() + ")"); 
     } 
    } 
} 
} 

クライアント

public class UDPClient { 
public static void main(String args[]) throws Exception { 
    byte[] send_data = new byte[256]; 

    BufferedReader infromuser = new BufferedReader(new InputStreamReader(System.in)); 

    DatagramSocket client_socket = new DatagramSocket(); 

    InetAddress IPAddress = InetAddress.getByName("localhost"); 

    System.out.println("Client - Initialized the client..."); 

    while (true) { 
     System.out.print("Client - Type Something (q or Q to quit): "); 

     String data = infromuser.readLine(); 

     if (data.equals("q") || data.equals("Q")) { 
      System.out.println("Client - Exited !"); 
      DatagramPacket send_packet = new DatagramPacket(send_data, send_data.length, IPAddress, 5000); 
      System.out.println("Client - Sending data : <" + data + ">"); 
      client_socket.send(send_packet); 
      break; 
     } else { 
      send_data = data.getBytes(); 
      DatagramPacket send_packet = new DatagramPacket(send_data, send_data.length, IPAddress, 5000); 
      System.out.println("Client - Sending data : <" + data + ">"); 
      client_socket.send(send_packet); 
     } 
    } 

    client_socket.close(); 
} 
} 

を私は間違いが些細なものですが、ネットワークプログラミングの私のスキルがあるとします限られているので、私はそれが何であるか分かりません。

サーバとクライアントの両方を別の端末の同じマシン(Mac)で実行していますが、状況に影響を与える場合があります。

ご協力いただければ幸いです。

EDIT

...そして私は自分の質問に答えるために戻ってきます。 問題は、サーバーソケットが読み取る予定のデータ量を定義していないことでした。 したがって、私はすべてが順調に働い

String data = new String(receive_packet.getData(), 0, receive_packet.getLength()); 

String data = new String(receive_packet.getData()); 

を変更したとき。ただ、今後の参考のために、同じ問題に遭遇するかもしれない人々のための

:)

+0

本当に正しいことを、あなたはバイトのいくつかの種類を行う必要があります文字変換へ? –

答えて

3

これはreceive_dataがどのように見えるかは、あなたの最初の呼び出しの場合:

:あなたの2番目の呼び出しで

-------------- 
|"a"| | | 
-------------- 

-------------- 
|"b"|"b"| "b" |    notice that the "a" in data_receive was overwritten 
-------------- 

3回目の呼び出しでは、1つの文字、 のみを送信するので、上書きされる配列の唯一の部分は最初の要素です:

-------------- 
|"c"|"b"| "b" | 
-------------- 

これは、サーバーへのメッセージの間にreceive_data配列に残っているデータがまだあるので、これを回避する簡単な方法は、ちょうどあなたがループを受けるの内側に新しい配列を初期化するだろう起こっています。そうすることで、メッセージを受け取るたびに新鮮な配列があなたを待ってくれます。

あなたはその結果に基づいて Stringを構築しているとき、あなたは現在、受信したパケットの長さを無視している
while (true) 
{ 
    byte[] receive_data = new byte[256]; 
    ...... 
} 
+0

あなたのソリューションも完璧に動作しました。ありがとうございました:) –

+0

@Sotirisありがとう、私はあなたのソリューションがより良いのが好きです。それはずっときれいだ。 –

4

DataSocket.receive(DatagramPacket)を使用した後、DatagramPacketの長さは、実際に受信された長さに設定されるべきである:

データグラムパケットオブジェクトの長さフィールドが 受信されたメッセージの長さを含んでいます。メッセージがパケットの 長さより長い場合、メッセージは切り捨てられます。あなたはまた、送信されたデータが正しいサイズであることを確認する必要が動作するように、このために

String data = new String(receive_packet.getData(), 0, receive_packet.getLength()); 

この

は、受信側の問題を修正する必要があります。特に、 DatagramPacketを構築するのに send_data.lengthを使用しないでください。これは常にバッファの全長を使用します)。 lengthパラメータは常に send_data.lengthであることを意味するものではありません。そうでなければ、コンストラクタ自体は配列から取得されます。これは、その配列内の実際のメッセージ長を意味します。

+0

まあ、自分で解決策を見つけたようです。私は入力を完了した時点で編集に気づいていませんでした。あなたは送信データ長について何も言及していません(あなたもそれを修正したと思います)。 – Bruno

0

問題を解決するには、receive_packetの長さを使用して文字列または配列を作成する必要があります。サーバ側でより高いパフォーマンスを得るために、それはしばらくのセクションの前receive_packetを初期化し、ループ内でそれを再利用するためにしばらくセクションの終わりにその長さをリセットするために、より良い
です:receive_packet.setLength(buffer.length);

関連する問題