第2回 JXTA-ShellとJXTA Java APIの関連
丸山不二夫
稚内北星学園大学学長
(http://www.wakhok.ac.jp/)
2001/10/31
本連載では、成長過程にあるJXTAのテクニカルな部分に触れながら、JXTAによって実現可能となるPtoPサービスの可能性にアプローチしていきたい。また、大きなリリースのタイミングでは、その詳細について解説する。(編集局) |
前回は、JXTA-Shellのメッセージ通信について見ましたが、今回は、こうしたスクリプトがJXTA Javaの「告知」を使ったメッセージ通信プログラムとどのように関連があるかを見てみたいと思います。
JXTA Shellのメッセージ通信のまとめ |
shareとsearchのソースを読む
JXTAのDiscoveryの働き(1)
今回は、shareコマンドとsearchコマンドのソースを読みます。JXTA-Shellのコマンド作成に必要な情報を紹介しながら、JXTAがどのように「告知」の公開・探索を行っているのかを見ていきたいと思います。
■JXTA-Shellのコマンド・クラスをどこに作るか
JXTA-Shellのコマンドは、すべてがnet.jxta.impl.shell.ShellAppクラスを継承して作られます。JXTA-Shellコマンドを作成するためには、このクラスのほかに、net.jxta.impl.shell.*以下のクラスが必要になります。
shareコマンド・クラスのパッケージ名とクラス名を示します。パッケージ名ですが、net.jxta.impl.shell.bin.+shareという形をしています。このshare以前の名前は予約されています。この固定部分にコマンド名(この例の場合にはshare)を付けたのが、Shellコマンド・クラスのパッケージ名になります。さらに、コマンド名と同じ名前のクラスが、このパッケージの中にある必要があります。
---------------------------------------------------------------------------------
package net.jxta.impl.shell.bin.share;
import net.jxta.impl.shell.*;
...........
...........
public class share extends ShellApp {
private Discovery disco=null;
ShellEnv env;
...........
...........
}
---------------------------------------------------------------------------------
もしもcmdXという名前のJXTA-Shellコマンドを作りたいのであれば、./net/jxta/impl/shell/bin/cmdX/cmdX.classというパス名を持つクラスファイルが必要だということです。なにか、cmdXが二重になっていると思われるかもしれませんが、そうではありません。もしも、コマンドcmdX用に補助的なヘルパー・クラスが必要であれば、これらのcmdXに関連するファイルたちを、cmdXディレクトリ以下に次のように配置すればいいのです。
---------------------------------------------------------------------------------
./net/jxta/impl/shell/bin/cmdX/cmdX.class
./net/jxta/impl/shell/bin/cmdX/cmdXHelper1.class
./net/jxta/impl/shell/bin/cmdX/cmdXHelper2.class
.............
./net/jxta/impl/shell/bin/cmdX/cmdXHelperN.class
./net/jxta/impl/shell/bin/cmdX/cmdXImage1.gif
.............
./net/jxta/impl/shell/bin/cmdX/cmdXIcon.ico
---------------------------------------------------------------------------------
JXTA Shellのメッセージ通信のまとめ |
■JXTA-Shellのイディオム --- getEnvとgetDiscovery
JXTA-Shellでは、コマンド文字列の実行はShellAppインスタンスのstartAppメソッドの呼び出しとして実行されます。このとき、コマンドに与えられていた引数たちは文字列の配列としてこのstartAppメソッドに渡されます。次に示すのは、shareコマンドのstartAppメソッドのリストです。
---------------------------------------------------------------------------------
public int startApp (String[] args) {
if ((args == null) || (args.length !=1)) { // 引数配列がnull、あるいは、1つ以外の引数を
return syntaxError(); // 持てば、エラー
}
env = getEnv(); // 環境とdiscoveryサービスを獲得する
disco = group.getDiscovery();
String name = args[0]; // share に与えられた引数=告知の名前
ShellObject obj = env.get ("stdgroup"); // 環境変数stdgroupに設定されている値を
PeerGroup group = (PeerGroup) obj.getObject(); // groupに設定する
obj = env.get (name); // 引数の告知は、あらかじめ変数に
if (obj == null) { // 入っていなければいけない
println ("share: cannot access " + name);
return ShellApp.appMiscError;
}
StructuredDocument doc = null;
Advertisement adv = null;
try {
adv = (Advertisement) obj.getObject(); // 引数の告知の名前から、告知を獲得する
publishAdv(adv); // 告知の公開
} catch (Exception e) {
println ("share: " + name + " is not a proper Document");
return ShellApp.appMiscError;
}
return ShellApp.appNoError;
}
---------------------------------------------------------------------------------
このソースの次の処理は、ほとんどすべてのJXTA-Shellコマンドで行われている基本的なイディオムといっていいものです。
---------------------------------------------------------------------------------
env = getEnv();
disco = group.getDiscovery();
---------------------------------------------------------------------------------
JXTA Shellのメッセージ通信のまとめ |
■Shell内部の変数の値を獲得するには
env = getEnv();のenvはShellEnvクラスのインスタンスで、JXTA-Shell内部の変数の値を獲得する際に用いられます。envはHashtableと同じようなものなのですが、直接変数を格納しているわけではなく、オブジェクトと変数名のペアから成るShellObjectというオブジェクトのインスタンスを格納しています。これは、変数名を表す文字列がnullのときに、自動的に変数名を生成して値を格納する際に利用される仕掛けなのですが、そのために、変数名を指定してその値を引き出すときには、次の例のように、いったんgetメソッドでShellObjectを獲得してから、getObjectメソッドを実行しなければなりません。
ShellObject obj = env.get ("stdgroup");
PeerGroup group = (PeerGroup) obj.getObject();
この2段階のシーケンスはよく登場しますので、このパターンを頭に入れておいてください。
JXTA Shellのメッセージ通信のまとめ |
■Discoveryインスタンスの獲得
Discoveryインスタンスのdiscoは、share/searchコマンドをはじめ、JXTA-Shellのいくつかのコマンドの中でdisco
= group.getDiscovery();で獲得されます。このdiscoは重要な役割を果たします。つまり、discoはShellAppクラスを拡大したコマンド・クラスの中でprivate
Discovery disco=null;と定義されているのですが、net.jxta.discovery.Discoveryはインターフェイスなので、正確にいえば、discoはDiscoveryインターフェイスを実装したインスタンスということになります。
次に、コマンドsearchのソースの一部を示します。ここでもgetEnvメソッドとgetDiscoveryメソッドが使われていることを確認してください。
---------------------------------------------------------------------------------
public class search extends ShellApp {
private ShellEnv env;
private Discovery discovery=null;
.............
.............
public int startApp(String[] args) {
env = getEnv();
discovery = group.getDiscovery();
.............
.............
try {
if (rflag || pflag ) {
return(discover(pid,attr,val));
} else {
return(getLocal(attr,val));
}
}
catch(Throwable ex) {
.............
}
}
---------------------------------------------------------------------------------
JXTA Shellのメッセージ通信のまとめ |
■shareコマンドとsearchコマンドの処理
先のshareコマンドとsearchコマンド、2つのstartAppメソッドのソースを眺めれば、shareコマンドの処理の中心がpublishAdv(adv);というメソッド呼び出しであり、searchコマンドの処理の中心がdiscover(pid,attr,val)とgetLocal(attr,val)いう2つのメソッド呼び出しであることが分かります。これらのメソッドのソースを次に示します。
---------------------------------------------------------------------------------
private void publishAdv(Advertisement adv) {
try {
disco.publish(adv, Discovery.ADV);
} catch( Exception ignored ) {
}
}
---------------------------------------------------------------------------------
---------------------------------------------------------------------------------
private int discover(String address, String attr, String val ) {
discovery.getRemoteAdvertisements(address,discovery.ADV, attr, val,threshold);
println("JXTA Advertisement search message sent");
return ShellApp.appNoError;
}
---------------------------------------------------------------------------------
---------------------------------------------------------------------------------
private int getLocal(String attr, String val) {
Enumeration res;
try {
res = discovery.getLocalAdvertisements(discovery.ADV, attr, val);
} catch (Exception e) {
println("nothing stored");
return ShellApp.appNoError;
}
..............
..............
}
---------------------------------------------------------------------------------
こうして整理すると、shareコマンドは基本的にはDiscoveryインスタンスに対するpublishメソッドの呼び出しであり、searchコマンドは同じくDiscoveryインスタンスに対するgetRemoteAdvertisementsメソッド、あるいはgetLocalAdvertisementsメソッドの呼び出しであることが分かります。
JXTA Shellのメッセージ通信のまとめ |
■publishメソッドとgetLocalAdvertisementsメソッド
net.jxta.impl.discovery.DiscoveryServiceクラスのpublishメソッドのソースの一部を示します。publishは、告知のタイプがGROUPかPEERかそのほかの告知かによって、基本的にはそれらのIDを取り込んで一意なファイルの名前を作り、告知のXMLドキュメントを格納しローカルなディレクトリ上に書き出します。
---------------------------------------------------------------------------------
public void publish(Advertisement adv, int type,
long timeoutForMe, long timeoutForOthers) throws IOException {
ID advID = null;
String advName = null;
// タイプは、GROUPかPEERか、それ以外か?
switch( type ) {
case GROUP :
advID = ((PeerGroupAdv)adv).getGid();
break;
case PEER :
advID = ((PeerGroupAdv)adv).getPid();
break;
default:
advID = ID.nullID;
break;
}
// 告知からXML文書を生成する
StructuredDocument doc;
try {
doc = (StructuredDocument) adv.getDocument(new MimeMediaType("text/xml"));
} catch (IOException error) {
throw error;
} catch (Exception everything) {
throw new IOException
("Advertisement couldn't be saved because of :"
+ everything.toString());
}
// 告知のXML文書を格納するファイル名を決める
if( advID.equals( ID.nullID ) )
advName = cm.createTmpName(doc);
else
advName = advID.getUniqueValue().toString();
if (LOG.isDebugEnabled()) {
LOG.debug("publishing " + advName + " in " + dirname[type]);
}
// cmディレクトリ下にセーブする
cm.save(dirname[type], advName, doc, timeoutForMe, timeoutForOthers);
}
---------------------------------------------------------------------------------
publishされた告知、また、次に見るgetRemoteAdvertisementsでネットワーク上で発見された告知は、具体的にはJXTAが起動されたディレクトリ下のcmという名前のディレクトリの下に、次のように収められています。画面1を参照してください。ここでは、Advと名付けられたディレクトリ下に、cmで始まる名前を持ついくつかのファイルがあることが分かりますね。このファイルの中にいくつかの告知がXML文書として公開されているわけです。
画面1(chache.jpg)
今回、getLocalAdvertisementsメソッドのソースは省略しますが、こうしたcmディレクトリ下のXMLドキュメントから、attributeやvalueといった検索条件に合致した告知たちを選び出す働きをしています。publishメソッドが告知を書き出して、getLocalAdvertisementsメソッドがそれを読み出すわけですから、この2つのメソッドは、相互に補い合う働きをしていることになります。
JXTA Shellのメッセージ通信のまとめ |
■getRemoteAdvertisementsメソッドのソースを読む
先の2つのメソッドが、ともにローカルに働いているのに対して、searchコマンドが-rオプションを付けて呼ばれたときに、内部で呼び出されるgetRemoteAdvertisementsメソッドは、ネットワークを越えてほかのPeer上の告知を見つけに行きます。Discoveryインスタンス上で定義されたこれらのメソッドのこうした働きは、本連載のJavaでのJXTAプログラムの紹介ですでに見てきました。
JXTA-Shellのコマンドが、JXTA-JavaのAPIを利用して書かれていることをこれまで見てきたのですが、publishやgetRemoteAdvertisementsといった、JXTA-JavaのAPIに登場するメソッドのソースも簡単に手に入ります。今回は、これらのソースのメソッドの内部の処理をもう少し詳しく見てみることにします。次に、getRemoteAdvertisementsメソッドのソースを示します。
---------------------------------------------------------------------------------
public int getRemoteAdvertisements(String peer, int type,
String attribute, String value, int threshold) {
DiscoveryQuery dquery = new DiscoveryQuery(type,
advToString(myGroup.getAdvertisement()),
attribute, value, threshold);
if ((attribute == null) || (value == null)) {
dquery.setAttr("null");
dquery.setValue("null");
} else {
dquery.setAttr(attribute);
dquery.setValue(value);
}
// Private copy for thread safety
int myQueryID = qid++;
LOG.debug("sending query: " + attribute + " = " +
value);
ResolverQuery query = new ResolverQuery(advertisement.getName(),
"JXTACRED", localPeerId, dquery.toString(), myQueryID);
resolver.sendQuery(peer, query);
return myQueryID;
}
---------------------------------------------------------------------------------
初めにDiscoveryQueryというクラスのインスタンスdqueryが生成されています。このインスタンスに、setAttrやsetValueを使い、引数で与えられているattributeやvalueの値を設定しているようです。続いてResolverQueryクラスのインスタンスを生成しています。そのコンストラクタの引数をよく見ると、dquery.toString()という形で、先に作ったdqueryインスタンスを文字列にしてqueryを作るのに使っていますね。このqueryがsendQueryメソッドの引数に与えられます。Resolverインスタンスに対するsendQueryメソッドの呼び出しが、getRemoteAdvertisementsメソッドの中心部分を構成しています。このnet.jxta.impl.resolver.ResolverServiceのsendQueryメソッドは、JXTAのメッセージ交換メカニズムの特徴をよく表しています。
JXTA Shellのメッセージ通信のまとめ |
■探索メッセージは、どのように送られるか?
ここでQueryと呼ばれているものは、まず、「これこれの告知を検索せよ」という探索命令だと考えてください。細かなメカニズムは後で見ることとして、最初に確認したいのは、各ピアは、こうしたQueryを受け取るとその問い合わせに対する「回答」を作り出して、それを質問者に送り返そうとするということです。探索ですから、できるだけ多くのPeerに対してこうした問い合わせを行う必要があります。問題は、Peer
to Peerの通信を特色とするJXTAが、どのようにして多数のピアに対する問い合わせを実行するかということです。
net.jxta.impl.resolver.ResolverServiceのsendQueryのソースを次に示します。このメソッドは、第1引数がnullのときには、まさに、たくさんのピアに探索メッセージを送りつける働きをします(逆に、第1引数が与えられれば、そのピアに対してだけ、メッセージを送ろうとします)。
---------------------------------------------------------------------------------
public void sendQuery(String rdvPeer,
ResolverQueryMsg query)
{
ResolverResponse doc=null;
LOG.debug("sending query");
Message propagateMsg = endpoint.newMessage();
if (rdvPeer == null){
try {
propagateMsg.push(outQueName,(InputStream)((Document)
(query.getDocument(new MimeMediaType("text/xml")))).getStream());
rendezvous.propagateInGroup(propagateMsg,
advertisement.getName(),
outQueName,
7,
null);
} catch (Exception e) {
LOG.info( "Error during propagate" ,e);
throw new RuntimeException ("Error during propagate :"
+e.toString());
}
} else {
//unicast instead
try {
respond (rdvPeer,
advertisement.getName(),
outQueName,
outQueName,
((Document)
(query.getDocument(new MimeMediaType("text/xml")))).getStream());
} catch (Exception e) {
LOG.info( "Error while unicasting query :", e );
throw new RuntimeException ("Error while unicasting query :"
+e.toString());
}
}
}
---------------------------------------------------------------------------------
問い合わせメッセージを、たくさんのピアに伝播(Propagate)する働きを担っているのは、次のpropagateInGroupです。後に、sendToNetwork、sendToEachRendezVous、sendToEachClientという3つのメソッドが並んでいますね。この3つのメソッドの並びが、JXTAに特徴的なPropagateの働きをよく表しています。
---------------------------------------------------------------------------------
public void propagateInGroup(Message msg, String serviceName,
String serviceParam, int defaultTTL,
String prunePeer)
throws IOException {
Message dupMsg = msg.dup();
if (updatePropHeader(dupMsg, defaultTTL)) {
sendToNetwork(dupMsg, serviceName, serviceParam, prunePeer);
sendToEachRendezVous(dupMsg, serviceName, serviceParam, prunePeer);
sendToEachClient(dupMsg, serviceName, serviceParam, prunePeer);
}
}
---------------------------------------------------------------------------------
sendToNetworkメソッドは、一番近い所に存在するピア同士がメッセージを交換するときに用いられます。同じネットワークに属するピア同士が、マルチキャストを通じて、メッセージを送るときに利用されるメソッドです。図1で、ピアAから、同一ネットワーク(正確にいえば、マルチキャスト・メッセージが到達可能なサブネット)内のピアB、C、Dに対するメッセージの送り出しです。
(図1入る)
sendToEachRendezVousは、あるピアから、そのピアが利用しているすべてのRendezVousに対してメッセージを送り出します。図2で、E、F、G、HはRendezVousを表しています。DからE、F、Gへの送り出し、CからHへの送り出しは、sendToEachRendezVousメソッドの働きを表しています。
(図2入る)
sendToEachClientが意味を持つのは、送り手側のピアがRendezVousである場合だけです。そうしたとき、このメソッドは、そのピアをRendezVousとしているすべてのクライアント・ピアに対してメッセージを送ります。図3で、RendezVousであるE、F、G、Hから発せられるメッセージが、このsendToEachClientメソッドの働きを示しています。
このようにして、この3つのメソッドを内に含む、propagateInGroupメソッドの働きによって、Aから出発した探索メッセージは、ネットワークの中に大きく広がることができます。このメソッドの第4引数であるdefaultTTLは、こうした拡大を無限に続けるのではなく、ここで指定された整数値のホップでpropagateを終了せよという意味を持っています。defaultでは、このTTL(Time To Live)の値は7に設定されています。
JXTA Shellのメッセージ通信のまとめ |
■Discoveryの働きの中間まとめ
Discoveryの働きの探索はまだまだ続きます。ここまでの過程を、ひとまずまとめておきましょう。
DiscoveryインスタンスでのgetRemoteAdvertisementsメソッドの呼び出しは、探索queryメッセージを引数に与えた、Resolverインスタンス上でのsendQueryメソッドの呼び出しを引き起こします。このことは、DiscoveryServiceがより基本的なサービスであるResolverServiceに「問題解決」の仕事を依頼していると考えることができます。ResolverServiceが解決すべき問題が、この場合は、「探索依頼」だったということです。
Resolverインスタンス上でのsendQueryメソッドの呼び出しは、今度は、Rendezvousインスタンス上でのpropagateInGroupメソッドの呼び出しを引き起こします。このメソッドによって、最初のgetRemoteAdvertisementsメソッドを発したピアからの探索queryは、ネットワーク上の数多くのピアに広がっていきます。
ところで、この最後のメッセージのPropagateの説明には少しおかしいところがあります。先に、propagateInGroup内の3つのメソッドの働きを3つの図で説明したのですが、それぞれのPropagateの中心には別のピアが存在しています。ピアAでpropagateInGroupメソッドが呼ばれたなら、ピアB、C、Dにはメッセージが届きますが、それ以上にはメッセージは広がらないはずです。
先の説明のようにメッセージが広がってゆくというのなら、メッセージを受け取ったピアが、バケツリレーのようにメッセージを、次のピアに送り出さなくてはなりません。JXTAには、実際そうしたメカニズムが組み込まれています。
次回は、JXTA?Discoveryの働きを、さらに見ていきたいと思います。
前回は、途中から2つのJXTA-Shellコンソールを使うことになったので流れが少し分かりにくかったかもしれません。あらためて、「受け手」側のコマンド列をまとめてみると次のようになります(先頭のJXTA>は、JXTA-Shellのプロンプトであり、コマンドの一部ではありませんので注意してください)。
「受け手」側 JXTA-Shellスクリプト |
JXTA>pipeadv = mkadv -p |
続いて、同じくJXTA-Shellでのメッセージの「送り手」側のコマンド列をまとめると次のようになります。
「送り手」側 JXTA-Shellスクリプト |
JXTA>opipe = mkpipe -o pipeadv |
JXTA-Shellで、このような「告知」を使ったパイプでのメッセージ通信のスクリプトがスラスラ書けるようになったら、JXTA-Shellのコマンドの主要な部分をほとんど使いこなせていると考えて間違いありません。マニュアルを見なくても、こうしたコマンド列が頭に浮かぶようになってください。
receiver.javaとsender.java |
今回は、Javaで書かれたJXTAでの通信プログラムで利用されているAPIが、JXTA-Shellでの通信のコマンド列ときれいに対応していることを見ていきます。「Viva! JXTA 〜JXTAはネットワークを変える」で紹介した2つのJavaプログラム、receiver.javaとsender.javaを再掲します。コメントを省いてありますので、印象が違うかもしれませんが同じものです。コメントなしでも、少し読んでみてください。
「受け手」側 Javaプログラム receiver.java |
public class receiver
extends ShellApp { private Discovery discovery;
|
「送り手」側 Javaプログラム sender.java |
public class sender extends ShellApp {
|
「受け手」のスクリプトとreceiver.javaの比較 |
まず、「受け手」のスクリプトとreceiver.javaの比較から始めましょう。
(1)パイプ告知の生成 |
JXTA-Shellのmkadvコマンドは、次のようにJavaプログラムのAdvertisementFactoryクラスでのnewAdvertisementメソッドの呼び出しに対応しています。mkadvコマンドの-pオプションは、newAdvertisementメソッドの引数jxta:PipeAdvertisementに対応します。
●パイプ・サービス告知を生成して、告知に必要なパラメータを設定する |
コマンド |
JXTA>pipeadv = mkadv -p |
Javaプログラム |
PipeAdvertisement
pipeAdv = (PipeAdvertisement) |
(2)パイプの生成 |
JXTA-Shellの-iオプション付きのmkpipeコマンドは、JXTA Javaでは、次のようにパイプ・サービス告知のインスタンスに対するcreateInputPipeメソッドの呼び出しに対応します。このメソッドは引数にパイプ告知を取っていますが、コマンドmkpipeも引数にパイプ告知pipeadvを用います。
●先に作ったパイプ・サービス告知を利用して、入力用のパイプを生成する |
コマンド |
JXTA>inpipe = mkpipe -i pipeadv |
Javaプログラム |
pipes = group.getPipe(); |
(3)メッセージの受け取り |
メッセージの受け取りは、Java APIではwaitForMessageメソッドが使われています。
●パイプ・サービス告知を生成して、告知に必要なパラメータを設定する |
コマンド |
JXTA>msg = recv inpipe |
Javaプログラム |
message = msgPipe.waitForMessage(); |
(4)メッセージ文字列の獲得 |
メッセージからタグの部分を取り出すJXTA-Shellのgetコマンドは、JXTA Javaでは、メッセージ・インスタンスに対するタグ文字列を引数とするpopメソッドの実行に対応します。この例でのJXTA-Shellのタグはmytagで、JXTA JavaでのタグはHelloTagです。
●メッセージからタグ部分を取り出す |
コマンド |
JXTA>data = get msg mytag |
Javaプログラム |
InputStream info =
message.pop ("HelloTag"); |
「送り手」のスクリプトとプログラムsender.javaの比較 |
今度は、「送り手」のスクリプトと、sender.javaの比較です。
(1)出力パイプの生成 |
JXTA-Shellの-oオプションを持ったmkpipeコマンドは、JXTA Javaのパイプ・サービス告知のインスタンスに対するcreateOutputPipeメソッドの呼び出しに対応しています。
●パイプ・サービス告知を生成して、ほかのピアに接続している「出力パイプ」を生成する |
コマンド |
JXTA>opipe = mkpipe -o pipeadv |
Javaプログラム |
pipes = group.getPipe(); |
(2)空メッセージの生成 |
JXTA-Shellで空のメッセージを生成するmkmsgコマンドは、JXTA JavaではcreateMessageメソッドに対応します。
●パイプ・サービス告知を生成して、告知に必要なパラメータを設定する |
コマンド |
JXTA>msg = mkmsg |
Javaプログラム |
message = pipes.createMessage(); |
(3)メッセージの形成 |
JXTA-Shellのgetコマンドが、JXTA Java APIのpopメソッドに対応していましたが、putコマンドにはpushメソッドが対応します。
●文字列にタグを付けてメッセージに押し込む。 |
コマンド |
JXTA>put msg mytag mydata |
Javaプログラム |
ByteArrayInputStream
info = new ByteArrayInputStream (strings.getBytes()); |
(4)メッセージの送出 |
JXTA-Shellのsendコマンドは、そのままJXTA Java APIのsendメソッドに対応しています。
●パイプ・サービス告知を生成して、告知に必要なパラメータを設定する |
コマンド |
JXTA>send opipe msg |
Javaプログラム |
msgPipe.send (message); |
さて、ここまでコマンドとJavaプログラムの対応を単純に比較してきました。次に、これらの間に考察を加えてみましょう。
なぜ、対応しない部分が存在するのか? |
Index | |
Page1 ● JXTA Shellのメッセージ通信のまとめ ●receiver.javaとsender.java ●「受け手」のスクリプトとreceiver.javaの比較 ●「送り手」のスクリプトとプログラムsender.javaの比較 |
|
Page2 ●なぜ、対応しない部分が存在するのか? ●「告知」の公開と獲得に、shareとsearchを使う ●「告知」をJXTA-Shellコマンドから獲得する ●searchコマンドの利用 |
|
連載記事一覧 |
- 実運用の障害対応時間比較に見る、ログ管理基盤の効果 (2017/5/9)
ログ基盤の構築方法や利用方法、実際の案件で使ったときの事例などを紹介する連載。今回は、実案件を事例とし、ログ管理基盤の有用性を、障害対応時間比較も交えて紹介 - Chatwork、LINE、Netflixが進めるリアクティブシステムとは何か (2017/4/27)
「リアクティブ」に関連する幾つかの用語について解説し、リアクティブシステムを実現するためのライブラリを紹介します - Fluentd+Elasticsearch+Kibanaで作るログ基盤の概要と構築方法 (2017/4/6)
ログ基盤を実現するFluentd+Elasticsearch+Kibanaについて、構築方法や利用方法、実際の案件で使ったときの事例などを紹介する連載。初回は、ログ基盤の構築、利用方法について - プログラミングとビルド、Androidアプリ開発、Javaの基礎知識 (2017/4/3)
初心者が、Java言語を使ったAndroidのスマホアプリ開発を通じてプログラミングとは何かを学ぶ連載。初回は、プログラミングとビルド、Androidアプリ開発、Javaに関する基礎知識を解説する。
|
|