3

私の Java アプリケーションでは、開いているソケットがあり、データはその InputStream から読み取られています。

最適な条件では、入ってくる各パケットは read() への呼び出しとなり、そのアプリケーション層データを返します。これは私が取得しようとしているものです-パケットごとに1つの「メッセージ」 。

ただし、 getReceiveBufferSize() が返すものに基づいて、データがソケットにバッファリングされる可能性があります。これが発生し、ストリームが読み取られる場合、そこに複数のパケットからのデータが存在する可能性があります。

個々のパケットからデータを取得する別の方法はありますか、それとも抽象化のレイヤーに違反していますか? または、データがバッファに追加されるときに何らかの区切り文字を設定することは可能ですか? それとも、プラットフォーム レベルで実行できないことですか?

私がやっていることを示すためのコード例を次に示します。

import java.io.InputStream;
import java.net.Socket;

public class Belnets {


public Belnets() {
    try{
        Socket s = new Socket("address", 23);
        System.out.println("platform will buffer this much: "+s.getReceiveBufferSize());
        InputStream sin = s.getInputStream();
        byte[] data = new byte[1024];
        int c;
        while(true){
            c = sin.read(data);
            for(int i=0; i<c; i++){
                System.out.print((char)data[i]);
            }
            System.out.println("=END OF READ=");

            //if you dont do this, read() seems to return once for each packet as this loop 
            //appears to be running fast enough to keep up with the rate of data that comes in.
            //otherwise data gets buffered and you get multiple packets worth of data before seeing
            //=END OF READ=
            Thread.sleep(1000);     

        }

    }catch(Exception e){
        e.printStackTrace();
    }
}   



public static void main(String args[]){
    new Belnets();
}

}
4

4 に答える 4

5

Java API には、TCP パケットを読み取る方法はありません。これはストリームベースであり、一度に 1 つのパケットを読み取る方法はまったくありません。

複数のメッセージを送受信する場合は、アプリケーション レベルのプロトコルを実装する必要があります。これは、メッセージ間に特定の区切り文字を使用するか、メッセージの長さに続いてメッセージ本文自体を送信するなどです。

于 2012-06-20T21:02:04.610 に答える
2

最適な条件では、入ってくる各パケットは read() への呼び出しとなり、そのアプリケーション層データを返します。

いいえ、これは「最適な条件」ではなく、まったくの運です。Java、基礎となる BSD Sockets API、または TCP RFC には、その動作に依存する権利を与えるものは何もありません。TCP はストリーミング プロトコルであり、API もバイトストリーム API です。

アプリケーション メッセージまたはパケットが必要な場合は、次の方法で自分で実装する必要があります。

  1. 各メッセージの先頭に長さの単語を付けます。
  2. オブジェクトのシリアル化、XDR などの上位レベルのプロトコルを使用します。
  3. XML、JSON などの自己記述型プロトコルを使用します。

いずれの場合も、メッセージ全体が得られるまで、受信側でループを読み取る必要があります。

于 2012-06-21T03:43:50.943 に答える
0

TCP パケットを読み取ろうとすることは実際には不可能であり、良い考えではありません。TCP はストリームベースであるため、すべてが一度に送受信される保証はありません。UDP (信頼性は低くなりますが、すべてが一度に送信されます) を使用するか、独自の区切り方式を考え出すことを検討してください。(一般的な方法は、「パケット」の長さに続いて実際のパケット自体を送信することです。)

于 2012-06-20T21:11:31.547 に答える
0

while ループを変更する必要があります。

while (true) {
    c = sin.read(data);
    if (c < 0)
        break;    // quit if there's nothing else to read.
    for(int i=0; i<c; i++){
        System.out.print((char)data[i]);
    }
...
}
于 2012-06-20T21:04:15.917 に答える