yamicha.com's Blog - Presented by yamicha.com
Blog yamicha.com's Blog - 2018/01 の記事
[1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19] [20] [21] [22] [23] [24] [25] [26] [27] [28] [29] [30] [31]

yamicha.com's Blog
 諸事情により、現在更新休止中。ご了承ください。もし今後ブログを再開することがあるとすれば、その際にはこのブログスクリプトではなく、新しく開発したものによるかもしれません。
 当ブログ管理者についてはこちらをご参照。
開発魔法(737)
社会問題(733)
お知らせ(11)
質問・バトン回答(15)
ゲスト出演(8)
経済・知的財産(150)
ゲーム開発(182)
[Ada] 勝手に補足
- Note
- 金配りの次の一手


- Endless Ultimate Diary
- 銃世界

漢字バトン
- うるる雑記帳
- 漢字接力棒

ツキアイゲノムバトン
- ブログ@うにうに画像倉庫
- あぶ内閣

縺イ縺セ縺、縺カ縺励ヰ繝医Φ
- 月夜のボヤキ
- 騎士サーラバトン
パスワードを使う
名無し (2012/02/27)


開発者解放裁判
yamicha.com (2010/03/14)
Winnyに関しては、私も「純白」とまでは考えておりませんし、使用し..

開発者解放裁判
通りすがり (2010/03/08)
winnyに関しては「ダウンロードソフト板」なんてところを拠点に開発..

新型インフルエンザの恐怖
いげ太 (2009/11/03)
> C#などの「int Some(int , int)」は、F#では「(int * int) ->..

時効に関する思考
yamicha.com (2009/08/31)
>いげ太さんコメントありがとうございます。手元にドキュメントが少..
Homepage
Blog Top
Normal View
List View
Search
Calendar
Comment List
Trackback List
Blog RSS
Send Trackback
Phone Mode
Administrator
yamicha.com
Blog
るううるる。
Source
法令データ提供システム
FindLaw
Development
Java2 Platform SE 6
Java EE 6 API
MySQL Developer Zone
PHP Reference
MSDN Library
Ada Reference Manual
Objective Caml
Python Documentation
Erlang
Prolog Documents
仲たがいする方々
2007/04/20(Fri)22:20:58
 長崎市長銃撃事件について、先に「これまでに発生した言論封殺テロでは、狙われたのが政府の意に反するような人であった場合には、政府は積極的な非難を行わなかった」と記述しましたが、まさにそれを地で行くかのような安倍コメントが発表されたことをご存知の方は多いでしょう。何と「真相究明を望む」意向を示すのみで、犯人に対する厳しい意見や言論封殺に対する憤りは述べられていないです。
 さすがに批判を浴びたようで、コメントを強めのものに差し替えたようですが、このあまりにもぞんざいな対応に対する私の意見は「やっぱり」です。安倍内閣の性質上、小泉政権時の政治家宅放火事件のようなぞんざいなコメントが出されるのではないかと予想していたら、案の定といいましょうか、的中してしまいました。予想はしていましたが、むなしいものです。
 この予想に至った経緯について少々説明しておきましょう。安倍内閣に限らず、政府は状況次第で地方自治体や住民と衝突してきました。公害や土地収用などもその1つですが、他にも原発、基地、平和などの点で主張がかち合うことは珍しくないようです。原発に関しては白羽の矢が立った地域の自治体や住民、基地については沖縄や他の移転候補地と対立することになります。
 では「平和」とは。小泉及び安倍内閣になってから、自衛隊のイラク派遣などがなし崩し的に進められ、憲法改正も現実味を帯びてきました。どうやら安部内閣は集団的自衛権を行使可能にし、ゆくゆくは憲法9条も変えたいと願っているようです。ところが、長崎や広島は原爆を落とされた場所であり、戦争の凄惨さを伝える建造物なども大量に残っています。市長などにも集団的自衛権や憲法9条改正に慎重な人が多いようです。平和と反戦を訴えて襲われた前の市長のように、その信念を口にしたり、行動で示したりする人も多いようです。
 こうしたことから、長崎市長の考えや行動は完全に安倍内閣の方針と衝突します。その結果が今回のコメントというわけです。とはいえ、いくら主張がかみ合わない相手であっても、何の落ち度もないのに突然射殺されたとなれば、ましてや暴力団追放行動を逆恨みされて殺されたとなれば、普通は厳しいコメントを出すものです。ところが、残念ながら小泉内閣と安倍内閣だけは違うのです。
 ここで想像していただきたいのは、ここに集団的自衛権の行使と憲法9条改正を強く訴える政治家がいたとして、この人が非合法組織から突然射殺されたという状況です。果たして安倍氏は「真相究明を望む」なる味気ないコメントだけで済ませようとするでしょうか。犯人に対する憤りをぶちまけ、テロは許さないと力説するのではないでしょうか。私が問題視するのはここなのです。

 HOYAとペンタックスの合併があさっての方向に。最初は友好的な対等合併を目指していたようですが、紆余曲折の末にHOYAがペンタックスへのTOBも検討すると言い出し、ペンタックス側は「そんな話は聞いていない」と大混乱。HOYAがTOBの機会をうかがう一方、ペンタックスはりそな銀行との関係を強化し、それを牽制しています。
 このところ、日本にも様々な合併あるいは合併未遂がありました。どこかと合併しなければ危ういことが最初から分かっている中堅企業に対し、複数の大手が合併を提案して合併後の計画を示し、中堅企業はその「マニフェスト」を比べた上で自ら合併先を決めた、というのが今のところ最もスマートな買収合戦の形でした。
 逆にあまりにこっけいなものとしては、売るに売れなくなった某社株を抱えたファンドが、お坊ちゃんが経営する企業に目をつけ、お坊ちゃん社長をおだてて操縦。ルールを無視した買収方法を伝授し、某社株を大量に買わせた裏で自分は売り抜け、という例がありました。結局、某社は「子会社が親会社の株を大量に握る」というスキにつけ込まれてこのような状況に追い込まれたのであり、蛮行を行ったお坊ちゃんやファンドのリーダーは今では被告の身です。因果応報といったところでしょうか。
 何とも野蛮なことに、とにかく「侵略戦争」を仕掛けて失敗した例といえば、かの「ティシュー王子」問題です。そういえば、日本で敵対的買収が功を奏した例はほとんどない気がします。これはおそらく日本に限ったことではなく、友好的に話を進められるのならその方が利益が大きいに決まっています。
 HOYAとペンタックスの場合、最初は友好的に話を進めていたのが、どうやら今では相互不信の状態にあるようです。友好的買収において、相互に油断ならないほどの不信感を生じるというのはかなり致命的です。かといって敵対的買収は失敗率も高く、成功したからといって良い結果を生むとは限りません。
 ちなみに、ペンタックスはカメラ事業にHOYAの技術を応用したいと考えているにもかかわらず、HOYAはペンタックスのカメラ事業を切り捨てて利益を強化しようとしているらしく、方針から違っています。目的が一致しない状況では、敵対的買収によって反発や士気の低下を招く可能性も高いことになります。
 こうなってしまったからには、再び努力して合併の流れを再構築するか、ダメなら合併をあきらめることが最善ではないでしょうか。
 ところで、楽天が再びTBSに手出しをしようとしているようです。楽天ももはや余計なことをしない方が自分のためなのでは。下手なことをすれば楽天の株(「株」といっても「株式」ではなく「お株」、つまり評判の方)が暴落するのは見えています。正直なところ、TBS株問題以降、私は楽天に良い印象を持っていません。これ以上問題を複雑にするようなら、所詮はライブドアと同類でしょう。
 TBSや同業者についても同じです。今後楽天が具体的な行動に出てくる可能性もありますが、その際に「ジャーナリズムを脅かす」「インターネットに比べて既存のマスメディアは優秀」などという意味不明な主張をひたすら並べ立てるのはやめるべきです。事実、ライブドアがニッポン放送に手を出した時の、新聞などの「ネット中傷」のひどいことといったら。本音を言わせていただけば、あの時ほどライブドアとフジサンケイグループの共倒れを願ったことはありません。
 また、敵対的買収防止策についての標準的な規定も定められるべきです。TBSは一応、敵対的買収防止策を作成していますが、これの有効性は極めて怪しいものです。もし楽天が本気でTBSを買収する気であれば、確実に司法での泥沼の争いになります。買収されそうな会社が買収防止策を発動しようとするたび、その是非が司法に持ち込まれるような状況は極めて問題です。防止策を盛り込んではみても、それが本当に行使できるかどうかは、実際に買収を仕掛けられるまで分からないのです。
 三角合併も解禁され、外資系企業やグリーンメーラーが大量に流入してくる可能性があるにもかかわらず、この状態はあまりにあいまい過ぎますし、危険でさえあります。TBSの「本当に役立つのか分からない買収防止策」を見るまでもなく、何とかすべきです。

 Ajaxとは何ぞや。「Asynchronous JavaScript + XML」なのですが、この略語には首をひねるばかりでした。略語にしてはあまりに下手すぎるのです。なぜ「JavaScript」の部分から2文字も取るのか全く不明ですし、「ja」では「Java」を連想しかねません。JavaとJavaScriptは完全なる別物ですから、このような勘違いの火種を残しておくのは問題です。
 ですから、普通に考えれば「AJX」か「AJSX」辺りが適当です。しかも、AjaxはもともとXMLを読み込む技術ですが、まじめにXMLを読み込んでいる人などごく少数です。JavaScriptで動作するHTTPソケットとして使われているのが現実です。すなわち、「Asynchronous JavaScript +」の次には「XML」ではなく「HTTP」や「Connection」、「Socket」などが来る方が自然なのです。略語は「AJH」「AJC」「AJS」のようになるでしょうか。
 さらに言えば、Ajaxでは非同期通信もできますが、同期通信もできます。そもそもスレッドなりを実装できる言語であれば、ソケットを使って非同期通信を作る程度のことは簡単ですから、「非同期」がことさら強調されるべきものとも考えられません。それなら「JavaScript HTTP Connector」(JHC)や「JavaScript HTTP Socket」(JHS)などとする方が適切なはずです。
 それなのになぜ「Ajax」という意味不明な名前になったのか。どうやら「Ajax」には意味があるようです。神話の固有名詞、軍艦の名前、サッカーチームの名前などに「Ajax」が存在するそうな。そして何といっても、米国には「Ajax」という洗剤があるらしいのです(ColgateのAjax紹介ページ)。
 実装の名づけに迷った挙句、とりあえず「ジョイ」とでもつけるようなノリなのでしょうか。ちなみに、米国にはカービィという掃除機があると聞いたことがあります。似たようなネタでは、マリオシリーズに登場する悪役の名前がどうしても決まらず、誰かが「クッパでも食べに行くか」と言ったことで「クッパ」に決まったとか(ちなみに英語版での名前は「Bowser」です)。
 とにかく、Ajaxとは何ともセンスのない名前と考えていたら、こういう裏があったのです。それで日本人には理解しがたいネーミングになっていたのですか。技術に洗剤の名前を付ける行為自体が理解しがたいことに変わりありませんが。ここは「神話から取った」ということにしておきましょう。
 ところで、Ajaxの登場によって「Comet」という技術が注目されています。HTTPは通常、リクエストを受け取ったら即座にレスポンスを返すものですが、それをあえて返さないようにしておき、任意のタイミングでリクエストを返すことで擬似的にリアルタイム通信を実現する技術です。Ajaxと組み合わせて使うことで、リアルタイムに近い作業が可能になります。
 で、「Comet」とは一体何なのでしょう。Ajaxには一応正式名称がありましたが、Cometに関しては正式名称を聞いたことがありません。正式名称がないなら、「Comet」と名づける意味もありません。なぜ「Comet」なのでしょうか。
 結論から言えば、これはアメリカンジョークでした。Cometといえば夜空を見上げたくなるような名前ですが、実際にはそういうロマンチックな経緯で名づけられたわけではないようです。それというのも、米国には「Comet Cleanser」という洗剤があるのです(Prestige BrandsのComet紹介ページ)。AjaxとCometは競争相手になります。
 なるほど、これがAjaxとCometのせんざい能力というものですか。何でも良いですが、技術の世界にこういう意味不明なことを持ち込む必要はないのでは。それ以前に、わざわざ略語に意味のある言葉を当てないで欲しいというのが本音です。紛らわしくなる一方です。もし意味のある言葉を当てるなら、Perl(病的折衷主義ガラクタ出力機)程度のセンスが欲しいところです。その上、読みは「パール」ですが、表記が「Pearl」ではないため、混乱することもありません。もしくはJavaのように略語でなく正式名称自体を単語とするか。
 それで、Ajaxとセットで語られがちなCometですが、実はセットである必要などどこにもありません(セットにしたものは以前にこちらの記事で作成済みです)。Ajax単体、またはComet単体で使っても何ら問題ないのです。とはいえ、Cometはブラウザそのもので使うには少々難のある技術です。ではどうすべきかといえば、アプリケーションを書いて使えば良いのです。
 無論、アプリケーションで非同期通信を行いたければ、ソケットを使うのが最も良いのですが、HTTPサーバーを使う必要があったり、ポートが開いていないなど、それができない状況も少なくありません。そうした場合にはCometの出番です。
 それではJSPとJavaアプリケーションを書いてみるとしましょう。JSPはフォームになっており、文字データを送信することができます。Javaアプリケーションはタスクトレイに常駐し、JSPでデータが送信されたらそれを検出してバルーンで通知します。
 まずはJSPから。
// comet.jsp
<%@page import="java.io.* , java.util.*" 
contentType="text/html;charset=Shift_JIS" %>

<%!
private CometData comet;
private ArrayList<String> datas;

class CometData{
	private String data;
	public String getData(){
		return data;
	}
	public void setData(String d){
		data = d;
	}
}

public void jspInit(){
	super.jspInit();
	comet = new CometData();
	datas = new ArrayList<String>();
}
%>

<%
request.setCharacterEncoding("Shift_JIS");

String mode = request.getParameter("mode");

if("check".equals(mode)){
	// Comet による擬似リアルタイムリクエスト
	String msg = "";
	try{
		synchronized(comet){
			while(msg.isEmpty()){
				comet.wait();	// 待機
				msg = comet.getData();
			}
		}
	}catch(InterruptedException e){
	}

	response.setContentType("text/plain;charset=Shift_JIS");
	out.print(msg);
}else{
	if("add".equals(mode)){
		String data = request.getParameter("data");
		if(data != null && !data.isEmpty()){
			if(data.length() > 50){
				data = data.substring(0 , 50);
			}
			synchronized(this){
				datas.add(data);
			}
			// データ更新を通知
			synchronized(comet){
				comet.setData(data);
				comet.notifyAll();
			}
		}
	}else if("remove".equals(mode)){
		boolean flag = false;
		synchronized(this){
			if(datas.size() > 0){
				flag = true;
				datas.clear();
			}
		}
		// データ削除を通知
		if(flag){
			synchronized(comet){
				comet.setData(
					"データがクリアされました。");
				comet.notifyAll();
			}
		}
	}
%>

<html>
<head>
<title>Comet Application</title>
</head>
<body>

<b>Comet Application</b><br>
 以下のフォームにデータを入力してください。データは50文字までです。

<form method="POST" action="?">
<input type="hidden" name="mode" value="add">
データ : <input type="text" name="data" size="40" maxlength="50">
<input type="submit" value="データの登録">
</form>

<form method="POST" action="?">
<input type="hidden" name="mode" value="remove">
<input type="submit" value="全データの削除">
</form>

<hr>

<%
synchronized(this){
	for(int i = datas.size() - 1; i >= 0; i--){
		out.println(datas.get(i) + "<hr>");
	}
}
%>

<div align="center"><small>yamicha.com Comet Application</small></div>

</body>
</html>

<%
}
%>
 ?mode=checkにリクエストがあったら、まずcomet.wait()で制御を止めます。データに変化が発生した際にはcomet.notifyAll()を呼び出し、待機スレッドを全部再開させます。
 comet変数には通知すべきデータが格納されるようになっており、comet.wait()を抜けたらすぐにString型の変数にデータを代入しています。これはsynchronized(comet)ブロック内で行われており、データの追加などcometが変更される処理もまたsynchronized(comet)ブロック内でのみ行われていますので、少なくともcomet.wait()から復帰し、cometに保持されたデータを取得するまでの間に、cometのデータが他のスレッドから書き換えられることはありません。
 このように、JSPでも少々面倒なマルチスレッドプログラミングですが、Javaアプリケーション側ではもう少し複雑さが増しています。必要なファイルは次の通りです。
Main.java
Looking.java
IconChanger.java
icon.gif - 普段のタスクトレイアイコン
icon_i.gif - 通知があった時のアイコン
 アイコンは好きなように作成して構いませんが、私は次のようなものを用いました。

icon.gif
icon_i.gif

 普段はicon.gifが用いられるのですが、通知後は10秒間だけicon_i.gifに変わります。とはいっても「10秒後にアイコンを戻す」などというメソッドは存在しませんから、IconChangerが10秒後にアイコンを元に戻す処理を受け持ちます。
 それでは実装と参りましょう。起点となるMain.javaは非常に単純です。
// Main.java
public class Main extends Thread{
	public static void main(String args[]) throws Exception{
		Looking look = new Looking();
		look.looking();
	}
}
 処理をすべてLooking.javaに任せていることが分かります。そして、実質的にLooking.javaがほとんどの処理を受け持っています。
// Looking.java
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;

public class Looking{
	private volatile boolean loop;

	private Image icon;
	private Image icon_i;
	private HttpURLConnection connection;

	private SystemTray systray;
	private TrayIcon tray;
	private IconChanger change;
	public Looking() throws Exception{
		Toolkit tool = Toolkit.getDefaultToolkit();
		icon = tool.getImage("icon.gif");
		icon_i = tool.getImage("icon_i.gif");

		loop = true;
		change = null;

		// トレイの構築
		systray = SystemTray.getSystemTray();

		PopupMenu popup = new PopupMenu();
		MenuItem m = new MenuItem("閉じる");
		m.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				synchronized(this){
					loop = false;
					connection.disconnect();
				}
			}
		});

		popup.add(m);

		tray = new TrayIcon(icon , "Comet Application" , popup);
		systray.add(tray);
	}
	public void looking() throws Exception{
		// URL は環境に応じて変更
		URL url = new URL(
			"http://www.localyamicha.com/comet.jsp?mode=check");

		while(true){
			synchronized(this){
				if(!loop)
					break;

				connection = (HttpURLConnection)url.
					openConnection();
				connection.setReadTimeout(0);

				connection.connect();
			}

			try{
				InputStream is = connection.getInputStream();
				String data = "";

				int read = 0;
				byte b[] = new byte[256];

				while((read = is.read(b)) != -1){
					data += new String(b , 0 , 
						read , "Shift_JIS");
				}

				if(is != null)
					is.close();

				// 改行を削除
				int trim = 0;
				while(trim < data.length()){
					if(data.charAt(trim) != '\n' &&
						data.charAt(trim) != '\r')
						break;
					trim ++;
				}
				data = data.substring(trim , data.length());

				tray.displayMessage("データの変更" , 
					"データに変更がありました:\n" + 
					data , TrayIcon.MessageType.INFO);
				tray.setImage(icon_i);

				if(change != null)
					change.setInvalid();
				change = new IconChanger(tray , icon , 10*1000);
				change.start();
			}catch(IOException e){
			}
		}

		if(change != null)
			change.setInvalid();

		systray.remove(tray);
	}
}
 IconChanger.javaは次の通り。当然ながらThreadの継承クラスです。
import java.awt.Image;
import java.awt.TrayIcon;

public class IconChanger extends Thread{
	private TrayIcon tray;
	private Image newicon;
	private long time;
	private boolean valid;
	public IconChanger(TrayIcon trayicon , Image icon , long t){
		tray = trayicon;
		newicon = icon;
		time = t;
		valid = true;
	}
	synchronized public void setInvalid(){
		valid = false;
		interrupt();
	}
	synchronized public void run(){
		try{
			wait(time);
		}catch(InterruptedException e){
		}

		if(valid)
			tray.setImage(newicon);
	}
}
 Cometをアプリケーションから使ってやろうというこのプログラムですが、書いている時には色々な問題に見舞われました。
 その中でも困ったのが、HttpURLConnectionから取得したInputStreamの仕様です。SocketのInputStreamはread()によるブロック中に別スレッドからclose()されるとIOExceptionを投げてくるのですが、HttpURLConnectionでは何とread()のブロックが解けるまでclose()メソッドがブロックされてしまうのです。
 これが何を意味するか。つまり、通信待機中にリスナからプログラムを終了させる通知(上記プログラムではPopupMenuの「閉じる」)が来た場合、InputStreamを強引にclose()してIOExceptionを発生させ、read()によるブロックから制御を戻してプログラムを終了させるということができないのです。もちろん、リソースの解放を考えなくて良いのであれば、メインスレッドAからスレッドBを作り、BからさらにCを作り、Cに通信処理を行わせておいて、BはC.join()で待機、リスナから終了の通知が来たらBに対してinterrupt()で割り込み、join()を強制的に解除して終了させれば良いのですが、これではInputStreamが閉じられません。閉じないとどうなるのかは分かりませんが、少なくとも良いことは起こらないでしょう。
 仕方がないので、InputStraemのread()のブロックに割り込むのはあきらめ、HttpURLConnectionのgetInputStream()に割り込むことにしました。JSPでは、outに対して何も出力していない状態であれば、out.flush()がなされるまで実際にデータが送られることはないようですので、JSPが実際にデータを送り始めるまではgetInputStream()でブロックされた状態が続くことになります。JSPが何らかのデータを送り始めると、getInputStream()からInputStreamが返り、読み込み操作を実行できるようになります。
 アプリケーション終了の通知が送られてきたら、HttpURLConnectionのdisconnect()で割り込みます。するとgetInputStream()がSocketException(extends IOException)を投げてくるため、ブロックから抜け出すことができます。
 この動作を正常に行うために、プログラムではsynchronized()ロックを使うようにしています。Looking.javaでsynchronizedを使っているのは以下の2箇所です。
// 1.入れ子クラス内
PopupMenu popup = new PopupMenu();
MenuItem m = new MenuItem("閉じる");
m.addActionListener(new ActionListener(){
	public void actionPerformed(ActionEvent e){
		synchronized(this){
			loop = false;
			connection.disconnect();
		}
	}
});

popup.add(m);
// ...

// 2.looking() 内
public void looking() throws Exception{
	// URL は環境に応じて変更
	URL url = new URL(
		"http://www.localyamicha.com/comet.jsp?mode=check");

	while(true){
		synchronized(this){
			if(!loop)
				break;

			connection = (HttpURLConnection)url.openConnection();
			connection.setReadTimeout(0);
			connection.connect();
		}

	try{
		InputStream is = connection.getInputStream();
		String data = "";

		// ...
 特に2番目の
while(true){
	synchronized(this){
		if(!loop)
			break;
 の部分、「while(loop)」にすれば良いではないかと指摘されそうですが、もちろん理由があります。
 loopをsynchronized内で評価し、そのsynchronized内でconnectionに新しいHttpURLConnectionを割り当て、接続を行っていますが、このような実装にしなかった場合、次のようなことが発生しかねないのです。

1.looking()実行中のスレッドがloopを評価、trueのため続行
2.actionPerformed()のスレッドがloopをfalseにし、connection.disconnect()を実行
3.looking()のスレッドがconnectionに新しい接続を代入し、接続を開始。disconnect()された接続はあわれガベージコレクタのお世話に
4.looking()のスレッドがgetInputStream()でブロックし、次のメッセージが送られてくるか、再び「閉じる」動作が実行されるまで、終了することができない

 上記実装では同じsynchronizedブロックでloopを評価した上、connectionを生成していますから、このsynchronizedブロックに突入する以前にloopがfalseにされていればループを抜けますし、synchronizedを抜けた後でloopがfalseになり、connection.disconnect()されたとしても、その後のgetInputStream()ですぐに例外を投げてくれます。マルチスレッドプログラミングはスリリングといいましょうか。
 こうして作ったからには、実際に使ってみましょう。まず「java Main」でプログラムを実行し、comet.jspで適当なメッセージを送ってみます。さて、送ったメッセージが通知されたでしょうか。


 通知を受けた画面。何やら本当にしゃべっているように見えるのですが。

 このアプリケーションですが、例えばチャットの入室者を監視するプログラムなどに応用できそうです。がんばればPerlなどでも作れないことはありませんし、単なるHTTPですのでソケットやポートなどの面倒なことを考える必要もありません。
 それにしてもバルーン表示は便利です。以前にC++で書いた時には、MSN Messenger風にログインを表示しようとしてウィンドウの扱いに四苦八苦したのですが、Javaならバルーンがこれほど簡単に使えてしまう上、タスクトレイさえサポートしていればどのOSでも動くのですから。
 とにかくCometは色々な使い方があるということで。「CometはWeb 2.0において重要な技術である」などという宗教団体の勧誘のようなことは言いませんが、「それなりに面白い」ものではあります。
カテゴリ [開発魔法][社会問題][経済・知的財産] [トラックバック 0][コメント 0]
<- 前の記事を参照 次の記事を参照 ->

- Blog by yamicha.com -