JavaでのStream Control Transport Protocol(SCTP)のサポートが、JDK 7の機能として承認されました。 APIとリファレンス実装の定義は、OpenJDK SCTPプロジェクトを通して実施されました。 この作業はJDK 7 マイルストーン3に統合されており、将来のすべての拡張で利用できます。
Stream Control Transport Protocol(SCTP)は、信頼性に優れたメッセージ指向のトランスポート・プロトコルであり、UDP(User Datagram Protocol)およびTCP(Transmission Control Protocol)と同じ階層に位置します。 SCTPはセッション指向であり、データを転送する前にエンドポイント間のアソシエーションを確立する必要があります。
SCTPはマルチホーミングを直接サポートしています。つまり、エンドポイントを複数のアドレスで表すことができ、各アドレスをデータの送受信に使用できます。このため、ネットワークの冗長性が確保されます。 2つのエンドポイント間のコネクションは、これらのエンドポイント間のアソシエーションと呼ばれます。 エンドポイントは、アソシエーション設定中にアドレスのリストを交換できます。 1つのアドレスがプライマリ・アドレスとして指定されます。これが、ピア・エンドポイントがデータの送信に使用するデフォルト・アドレスとなります。 あるエンドポイントの特定のセッションでは、アドレス・リスト全体で単一のポート番号が使用されます。
SCTPはメッセージベースです。 I/O処理はメッセージに対して行われ、メッセージ間の境界が維持されます。 各アソシエーションは複数の独立した論理ストリームをサポートできます。 各ストリームは、単一のアソシエーション内部におけるメッセージ・シーケンスを表し、ストリームは互いに独立しています。つまり、ストリーム識別子とシーケンス番号がデータ・パケットに含まれており、ストリームごとにメッセージのシーケンスを設定できます。
Java APIは、NIOチャネル・フレームワークをベースとしています。このため、SCTPを必要とするアプリケーションは、ブロッキングなしの多重化I/Oを活用できます。新しいクラス/インタフェースを格納するための新しいパッケージcom.sun.nio.sctpが定義されています。 パッケージ名はcom.sun.nio.sctpです。java.nio.channels.sctpなどの形式にはなっていません。
この違いは、APIと実装は完全にサポートされ公開されますが、Java SEプラットフォームには含まれないことを表しています。 業界でSCTPに関する経験がもっと積まれた後に、標準APIが定義できることになります。
このパッケージ内のメイン・クラスは、新しい3種類のチャネル・タイプを表します。 これらの新しいチャネルは、2つの論理グループに分類できます。
SctpChannelとSctpServerChannelです。 SctpChannelは、単一のアソシエーション、つまり、単一のエンドポイントに入出力するデータの送受信のみを制御できます。 SctpServerChannelは、そのソケット・アドレス上で開始された新しいアソシエーションをリスニングし、受け入れます。SctpMultiChannelのみで構成されます。 このチャネル・タイプのインスタンスは複数のアソシエーションを制御できます。そのため、異なる複数のエンドポイントに入出力するデータを送受信できます。SCTPスタックはイベント駆動型であり、アプリケーションは特定のSCTPイベントの通知を受け取ることができます。 これらのイベントは、SctpMultiChannelと使用するともっとも有効です。このクラスは複数のアソシエーションを制御できるので、通知の状況を追跡する必要があります。 たとえば、AssociationChangeNotificationは、新しいアソシエーションの開始または終了を通知します。 アソシエーションが動的なアドレス設定をサポートしている場合、PeerAddressChangeNotificationは、ピア・エンドポイントに追加された、またはピア・エンドポイントから削除されたIPアドレスを通知します。 MessageInfoを使用すると、送信中または受信中のメッセージの補助的なデータを使用できます。
次の例では、SCTPのマルチストリーミング機能について示します。 この例のサーバーは、あるタイプの日時プロトコルを実装します。 一方のストリームでは英語(米国)形式、もう一方のストリームではフランス語形式でフォーマットした現在の日時を送信します。
コードを読みやすくするため、エラー処理は省略しています。
次に、DaytimeServerのソース・コードを示します。
publicclassDaytimeServer{
staticint SERVER_PORT =3456;
staticint US_STREAM =0;
staticint FR_STREAM =1;
staticSimpleDateFormatUSformatter=newSimpleDateFormat(
"h:mm:ss a EEE d MMM yy, zzzz",Locale.US);
staticSimpleDateFormatFRformatter=newSimpleDateFormat(
"h:mm:ss a EEE d MMM yy, zzzz",Locale.FRENCH);
publicstaticvoid main(String[] args)throwsIOException{
SctpServerChannel ssc =SctpServerChannel.open();
InetSocketAddress serverAddr =newInetSocketAddress(SERVER_PORT);
ssc.bind(serverAddr);
ByteBuffer buf =ByteBuffer.allocateDirect(60);
CharBuffer cbuf =CharBuffer.allocate(60);
Charset charset =Charset.forName("ISO-8859-1");
CharsetEncoder encoder = charset.newEncoder();
while(true){
SctpChannel sc = ssc.accept();
/* get the current date */
Date today =newDate();
cbuf.put(USformatter.format(today)).flip();
encoder.encode(cbuf, buf,true);
buf.flip();
/* send the message on the US stream */
MessageInfo messageInfo =MessageInfo.createOutgoing(null,
US_STREAM);
sc.send(buf, messageInfo);
/* update the buffer with French format */
cbuf.clear();
cbuf.put(FRformatter.format(today)).flip();
buf.clear();
encoder.encode(cbuf, buf,true);
buf.flip();
/* send the message on the French stream */
messageInfo.streamNumber(FR_STREAM);
sc.send(buf, messageInfo);
cbuf.clear();
buf.clear();
sc.close();
}
}
}
次に、DaytimeClientのソース・コードを示します。
publicclassDaytimeClient{
staticint SERVER_PORT =3456;
staticint US_STREAM =0;
staticint FR_STREAM =1;
publicstaticvoid main(String[] args)throwsIOException{
InetSocketAddress serverAddr =newInetSocketAddress("localhost",
SERVER_PORT);
ByteBuffer buf =ByteBuffer.allocateDirect(60);
Charset charset =Charset.forName("ISO-8859-1");
CharsetDecoder decoder = charset.newDecoder();
SctpChannel sc =SctpChannel.open(serverAddr,0,0);
/* handler to keep track of association setup and termination */
AssociationHandler assocHandler =newAssociationHandler();
/* expect two messages and two notifications */
MessageInfo messageInfo =null;
do{
messageInfo = sc.receive(buf,System.out, assocHandler);
buf.flip();
if(buf.remaining()>0&&
messageInfo.streamNumber()== US_STREAM){
System.out.println("(US) "+ decoder.decode(buf).toString());
}elseif(buf.remaining()>0&&
messageInfo.streamNumber()== FR_STREAM){
System.out.println("(FR) "+ decoder.decode(buf).toString());
}
buf.clear();
}while(messageInfo !=null);
sc.close();
}
staticclassAssociationHandler
extendsAbstractNotificationHandler
{
publicHandlerResult handleNotification(AssociationChangeNotificationnot,
PrintStream stream){
if(not.event().equals(COMM_UP)){
int outbound =not.association().maxOutboundStreams();
int inbound =not.association().maxInboundStreams();
stream.printf("New association setup with %d outbound streams"+
", and %d inbound streams.\n", outbound, inbound);
}
returnHandlerResult.CONTINUE;
}
publicHandlerResult handleNotification(ShutdownNotificationnot,
PrintStream stream){
stream.printf("The association has been shutdown.\n");
returnHandlerResult.RETURN;
}
}
}
出力例は、次のとおりです。
>: java DaytimeClient
New association setup with32 outbound streams,and32 inbound streams.
(US)4:00:51 PM Fri15May09,BritishSummerTime
(FR)4:00:51 PM ven.15 mai 09,Heure d'ete britannique
The association has been shutdown.
この記事に対するコメントをご投稿ください。また、SCTP開発メーリング・リストまでお気軽にご連絡ください。
Chris Hegartyは、アイルランドにあるSun Microsystemsのソフトウェア・エンジニアです。 余暇は、スーパーバイクのライディングを楽しんでいます。