8

これは、OOB(緊急)データを使用しようとしているいくつかの基本コードです。私の問題は、クライアントがCまたはJavaの場合、サーバー部分が同じように動作しないことです。注意してください、あなたは両方のクライアント側で何かがトリッキーだと思うかもしれませんが、私がCサーバーを使用する場合(OOBのより細かい制御を得るために)、両方のクライアントは私のサーバー側のOOB制御とまったく同じように動作します。

最初にサーバー(Java)の部分:

Socket s = ss.accept();
s.shutdownOutput();
s.setOOBInline(true);
InputStream is = s.getInputStream();
for (;;) {
  byte []d = new byte[3];
  int l = is.read(d);
  if (l==-1) break;
  for (int i=0; i<l; i++) System.out.print((char)d[i]);
  System.out.println();
  Thread.sleep(2000);
}

次に、クライアント(Java)の部分:

Socket s = new Socket("localhost",61234);
s.shutdownInput();
OutputStream os = s.getOutputStream();
byte []n = new byte[10];
for (int i=0; i<n.length; i++) n[i] = (byte)('A'+i);
byte m = (byte)('0');   
os.write(n);
System.out.println("normal sent");
s.sendUrgentData(m);
System.out.println("OOB sent");
os.write('Z');
System.out.println("normal sent");

次に、代替クライアント(C)の部分:

s = socket(PF_INET,SOCK_STREAM,0);
bzero(&a,sizeof(a));
a.sin_family = AF_INET;
a.sin_port = htons(61234);
a.sin_addr.s_addr = inet_addr("127.0.0.1");
connect(s,(struct sockaddr *)&a,sizeof(a));
shutdown(s,SHUT_RD);
char m = '0';
char *n = "ABCDEFGHIJ";

printf("normal sent %d\n",write(s,n,strlen(n)));
printf("OOB sent %d\n",send(s,&m,1,MSG_OOB));
printf("normal sent %d\n",write(s,"Z",1));

これが私が得たものです(最初にCクライアント、次にJavaクライアント):

Accepting connection
ABC
DEF
GHI
J
Z
Accepting connection
ABC
DEF
GHI
J
0Z

JavaサーバーはCクライアント側から送信されたOOBデータを見ることができないようです。なぜ0失われたように見えるのですか?サーバーは少なくともストリーム内のoob境界を検出しているため、検出されていません。

4

2 に答える 2

5

帯域外データは、すべてのSockets実装で同じようにサポートされているわけではありません。それはそれと同じくらい簡単です。

Microsoftのアドバイスはここにあります:

現在、RFC 793(概念が導入されている場所)には2つの矛盾する解釈があります。

Berkeley Software Distribution(BSD)でのOOBデータの実装は、RFC1122で指定されているホスト要件に準拠していません。

具体的には、BSDのTCP緊急ポインタは緊急データバイトの後のバイトを指し、RFC準拠のTCP緊急ポインタは緊急データバイトを指します。その結果、アプリケーションがBSD互換の実装からRFC 1122と互換性のある実装に緊急データを送信すると、受信者は間違った緊急データバイトを読み取ります(データストリームの正しいバイトの後にあるバイトを緊急データとして読み取ります)バイト)。

相互運用性の問題を最小限に抑えるために、既存のサービスとの相互運用に必要な場合を除いて、アプリケーション作成者はOOBデータを使用しないことをお勧めします。Windows Socketsのサプライヤは、自社の製品が実装するOOBセマンティクス(BSDまたはRFC 1122)を文書化することをお勧めします。

新しいプロトコルを作成していて、帯域外データが必要な場合は、緊急データ用に別の接続が必要であるか、アプリケーション層で多重化する必要があることをお勧めします。

したがって、選択肢があれば、OOBデータを使用しないことをお勧めします。

于 2013-03-06T15:23:49.720 に答える
1

わかりました。これはJVMの実装に関連しているようです。さまざまなOSとJVMでさまざまなテストを行いました。

JDK 1.6を使用するさまざまなLinuxですべてが正しい(Java 7はテストされていません)。

しかし、私のMountain Lionには問題があり、Javaのバージョンによって動作が異なります。Appleの実装に関連するJVMのバグのようです。

于 2013-03-06T14:49:14.723 に答える