2006年7月12日水曜日

TcpClientのメモ

.NET Frameworkに用意されている各種ネットワークアクセスクラス(WebClient, WebRequest/WebResponse, SmtpClient)ではなく、あえて低レベルのTcpClientを使うときもあります。そんなときのための注意点を。


ストリームの終わりをどのように判断するか、これは悩ましいところですが、NetworkStream.DataAvailableを使うのはやめておいたほうがいいです。送信元がデータを送るとき、いつでも全部まとめて送信するわけではないからです。たとえば、ある瞬間にはDataAvailableがfalseになっていても、1秒後にはtrueになったりします。「じゃあ、NetworkStream.DataAvailableがfalseならしばらく待ってみて、それでもfalseだったら読み取り終了にすればいいじゃないか」というのは筋が悪いです。いったい何秒まてば十分なのかは誰にも分からないですし、それに無駄な待ちが必ず発生することになりますしね。
結局のところ、規定の長さに達するまでStream.Readするか、またはデータの区切り(CrLfなど)が届くまでStream.ReadByteを繰り返すか、そのどちらかを選択するのがいいでしょう。もちろん、どちらを選ぶかはプロトコル次第ということになります。そのように実装すると、データの終わりを受け取るまではブロックすることになります。ですので、適切なタイムアウトは必須でしょう。


データの区切りが(CrLfなど)決まっている場合はStream.ReadByteを繰り返せと書きましたが、反論が2つ考えられます。1つ目は「区切りがCrLfなら、StreamReaderを使ってReadLineした方が簡単」という意見と、もうひとつは「1バイトずつStream.ReadByteするのは遅い」という意見です。


最初の意見ですが、もし送られてくるデータが全て文字列で、しかも最初から最後までエンコーディングが固定されているのなら、そのエンコーディングに対応したStreamReaderを使うのもいいでしょう。ですが、そうでないなら、つまりエンコーディングはデータを受け取るまで分からないとか、あるいは途中からは生のバイト列が必要になるとか、そういう場合はStreamReaderは向いていません。StreamReaderはストリームの先読みをして、内部でバッファリングします。ですので、「次の行からはエンコーディングの異なるStreamReaderを使う」とか「次の行からはバイト列」といったときに、ストリームの位置は次の行の先頭よりも先に進んでいます。要するに、StreamReaderを使った場合は、もう元のStreamは使えないと考えるべきなのです。(天邪鬼な人はISO-8859-1エンコーディングを持ち出すかもしれませんが、その議論はここではしません。「できるけど、ムダが多い」とだけ述べておきます。)


もうひとつの意見、つまりReadByteは遅いという意見ですが、それは生のNetworkStreamを1バイトずつ読み取るから非効率なので、そういう時はBufferedStreamでラップしてやればいいのです。もちろん、BufferedStreamは内部でバッファリングしますから、BufferedStreamを使った場合は、もうもとのStreamは使えないことに注意しなければなりませんが、大きな問題にはならないでしょう。

2006年6月21日水曜日

WEB+DB PRESS Vol.33

Web+DB Press Vol.33
見本誌いただきました。いつもありがとうございます。

今号もあちこちで大評判ですね。有名な方達が何人も執筆者に名を連ね……。
「.NET 開発天国」も負けないように面白ネタを提供しないといけないですね。「面白」はFunnyを重視しているきらいもありますが:-p もちろんInterestingも目指さないと。

2006年6月7日水曜日

続々・C# 2.0でカリー化を考えてみる。

連続して束縛することを考えれば、こんな形のほうがいいかな?(修正しました)

class Program
{
static void Main(string[] args)
{
GenericFunctions.CurriedFunc<int, int, double> cf =
Curry.Create<int, int, double>(Devide);
Console.WriteLine(cf(3)(2));
Console.ReadLine();
}

public static double Devide(int x, int y)
{
return (double)x / (double)y;
}
}

class Curry
{
public static GenericFunctions.CurriedFunc<T0, T1, U> Create<T0, T1, U>
(GenericFunctions.Func<T0, T1, U> f)
{
return delegate(T0 arg0)
{
return delegate(T1 arg1)
{
return f(arg0, arg1);
};
};
}

public static GenericFunctions.CurriedFunc<T0, T1, T2, U> Create<T0, T1, T2, U>
(GenericFunctions.Func<T0, T1, T2, U> f)
{
return delegate(T0 arg0)
{
return delegate(T1 arg1)
{
return delegate(T2 arg2)
{
return f(arg0, arg1, arg2);
};
};
};
}
//以下略
}

namespace GenericFunctions
{
public delegate U Func<T0, U>(T0 arg0);
public delegate U Func<T0, T1, U>(T0 arg0, T1 arg1);
public delegate U Func<T0, T1, T2, U>(T0 arg0, T1 arg1, T2 arg2);
public delegate U Func<T0, T1, T2, T3, U>(T0 arg0, T1 arg1, T2 arg2, T3 arg3);
//以下略

public delegate Func<T1, U> CurriedFunc<T0, T1, U>(T0 arg0);
public delegate CurriedFunc<T1, T2, U> CurriedFunc<T0, T1, T2, U>(T0 arg0);
//以下略
}

続・C# 2.0でカリー化を考えてみる。

引数をひとつずつ束縛するのに限定するなら、
いっぱいオーバーロードすれば実用上は問題ないのだった。
ただし、型推論が欲しくなる。

class Program
{
static void Main(string[] args)
{
GenericFunctions.Func<int, double> curried1 =
Curry.Bind<int, int, double>(Devide, 3);
GenericFunctions.Func<double> curried2 =
Curry.Bind(curried1, 2);
Console.WriteLine(curried2());
Console.ReadLine();
}

public static double Devide(int x, int y)
{
return (double)x / (double)y;
}
}

public class Curry
{
public static GenericFunctions.Func<U> Bind<T0, U>
(GenericFunctions.Func<T0, U> f, T0 arg0)
{
return delegate()
{
return f(arg0);
};
}

public static GenericFunctions.Func<T1, U> Bind<T0, T1, U>
(GenericFunctions.Func<T0, T1, U> f, T0 arg0)
{
return delegate(T1 arg1)
{
return f(arg0, arg1);
};
}

public static GenericFunctions.Func<T1, T2, U> Bind<T0, T1, T2, U>
(GenericFunctions.Func<T0, T1, T2, U> f, T0 arg0)
{
return delegate(T1 arg1, T2 arg2)
{
return f(arg0, arg1, arg2);
};
}
// 以下略
}

namespace GenericFunctions
{
public delegate U Func<U>();
public delegate U Func<T0, U>(T0 arg0);
public delegate U Func<T0, T1, U>(T0 arg0, T1 arg1);
// 以下略
}

2006年5月8日月曜日

C# 2.0でカリー化を考えてみる。


class Program
{
static void Main(string[] args)
{
Curry<double> c = new Curry<double>();
Program p = new Program();
Curry<double>.CurriedFunc cf = c.Make(p, "Devide");
Console.WriteLine(cf(2)(3));
Console.ReadLine();
}

public double Devide(int x, int y)
{
return (double)x / (double)y;
}
}

class Curry<T>
{
public delegate T BoundFunc(params object[] args);
public delegate BoundFunc CurriedFunc(params object[] args);

public CurriedFunc Make(object instance, string methodName)
{
MethodInfo mi = instance.GetType().GetMethod(methodName);
return delegate(object[] pre)
{
return delegate(object[] post)
{
ArrayList al = new ArrayList();
al.AddRange(pre);
al.AddRange(post);
return (T)mi.Invoke(instance, al.ToArray());
};
};
}
}

ジェネリクスを使う意味がよくわからない。
あとこれだとcf(1)(2)(3)(4)みたいに何度も束縛できない。
いまいちだなあ。

2006年5月7日日曜日

Prince Ice World 2006

プリンススケートリンク
プリンス アイスワールド2006を観てきました。
新横浜にはプリンスホテルが所有するスケートリンクがあるんですよ。そこで開催されるアイスショー「プリンス アイスワールド」は1978以来毎年開催されている、歴史のあるアイスショーなんです。
あの荒川静香もプリンスホテル所属で、今回出演します。生イナバウアー!ってなもんですよ。

……遅刻してしまいました。おかげで、浅田真央と中野友加里を見逃してしまった!
でも浅田舞、村主章枝、荒川静香はちゃんと観れました。

ともあれ楽しみました。現役の有名選手たちもすごかったんですが、それだけではないんです。プロに転向している八木沼純子をはじめとするプリンスのアイスショーチームたちのショーも、工夫されていて楽しめるものになってましたよ。
浅田舞
村主章枝

2006年5月6日土曜日

あほブレイクビート2

クイーン「Another one bites the dust」のリフをバックに、オリエンタルラジオの武勇伝

えーと、仕事してないときはこういうことばっかり考えています。

2006年5月2日火曜日

倉庫番は楽しい

携帯アプリで倉庫番を楽しんでいます。
ところが、44面で詰まってしまいました。
Stage44 Start
あまりに悔しかったので、倉庫番を解くソフトを試してみました。
とはいえ、全ステップを見てしまうとつまらないので、途中までしか見ていないのですが。

えー、ここから解けるの?
Stage44 Halfway

2006年4月11日火曜日

BON JOVI "HAVE A NICE DAY"

ライヴに行けなくなった友人からチケットを譲り受けて参加。
人生初ドーム。
席は一塁側スタンド。向きは正面に近かったけど、2階席のほぼ最後尾。ステージが遠い。
bonjovi開演前
客電が落ちて歓声が上がったその時、ステージにバンドが登場……あ、ジョンだけアリーナのど真ん中にいる!
その場で1曲歌った後、ステージに戻っていった。
bonjovi開演直後
そこですかさず"You Give Love A Bad Name"。
おー、過去のヒット曲もやってくれるんだね。最新アルバムの曲ばかり演奏されたらどうしようと思っていたところ。なにしろ予習ゼロ。唯一わかるのは"Have A Nice Day"の、しかもサビんとこの「♪ハヴァ・ナイス・デー!」だけという体たらくだったので。

とか考えてたら、本編ラストはヒット曲連発。すごいすごい。
"I'll Be There For You"は1本のマイクでJohnとRichieがハモる。これは萌えポイントですよ?
"Bed Of Roses"で観客がどよめく。

アンコールは2回。トータル2時間30分。もういい年なのに体力あるね。
そうそう、ジョンもリッチーも、やっぱりけっこう老けてきたよなー、とか思ってたら、ドラマーの人だけちょうムッキムキで、スクリーンに映るたびに噴出しそうになった。

ちなみに叶姉妹がアリーナ席にいたようです。

-- セットリスト
Last Man Standing
You Give Love A Bad Name
Complicated
Born To Be My Baby
Story Of My Life
Captain Crash & The Beauty Queen From Mars
I'd Die For You
The Radio Saved My Life Tonight
Everyday
In These Arms
Welcome To Wherever You Are
I Won't Back Down (トム・ペティ)
Have A Nice Day
Who Says You Can't Go Home
It's My Life
I'll Be There For You(アコースティック)
Bed Of Roses(アコースティック)
Bad Medicine
Raise Your Hands
Livin' On A Prayer

~encore~
Bells Of Freedom
Last Cigarette
Runaway
I'll Sleep When I'm Dead
Keep The Faith

~encore~
Someday I'll Be Saturday Night
Wanted Dead Or Alive
bonjoviステージ