すがブロ

sugamasaoのhatenablogだよ

FTPクライアントを作ってみよう(6)

前回(id:seiunsky:20061101:1162404086)

実は、前回のプログラムではデータの受信がうまく行っていなかった。

スレッド対策をすることで何故か問題が解決したので、まあいいかと思っていたのだが、BackGroundWorkerを使うようにしてから再発してしまった(id:seiunsky:20061122:1164233420)。
で、最初はスレッドにしているのが問題なのかと思っていたけど、ステップ実行時やコンソールに値を出力するようなプログラムにして動かすときちんとデータが取れている。

どうも、NetworkStream.DataAvailableがまずいようだ。

というのも、デバッグ情報をコンソールに出力したりすると、画面描画のために実行速度が遅くなる。そのようなウェイトがかかっているときは大抵データをきちんと取れていて、ウェイトがかからない状態だとDataAvailableの状態がきちんと取れないようだ。
で、当初DataAvailableがtrueの時を条件としてwhile文を書いていたから、状況によって全然値が取れない、ということになっていたようだ。
DataAvalibleが怪しいと睨んで調べてみたら↓のような記述があった。FTPやPOP3では無いものの、まさにこの症状だ。
FTPでダウンロードするファイルのバイト数を知る方法 - Insider.NET
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=2658&forum=7
ちょっとここら辺を参考にして解決策を調べてみよう。というか、日本語の情報が全然ねーんだけど。
ちなみに、以下は検証のために超手抜きでネットワークへアクセスするプログラム。変数名に統一感がないとか宣言の場所が気に食わないとかあるだろうけど、問題を切り分けるためだけに書いたのでそこまで突っ込まないで欲しい。
使い方は以下のクラスを生成してconnectメソッドすれば良い。おれはこのメソッドを使って普通に実行すると何の文字列も得ることが出来なかった。。。

using System;
using System.Collections.Generic;
using System.Text;

using System.Net;
using System.Net.Sockets;

namespace telnetConsole
{
	class telnet
	{
		private string URL = "www.yahoo.co.jp";
		private string Address = "";
		private int port = 80;

		private IPAddress[] ip;
		private TcpClient client;
		private NetworkStream ns;

		public string connect() {
			ip = Dns.GetHostAddresses(URL);
			Address = ip[0].ToString();
			client = new TcpClient();
			client.Connect(Address, port);
			ns = client.GetStream();
			byte[] buff = System.Text.Encoding.ASCII.GetBytes("GET /index.html \r\n\r\n");

			ns.Write(buff, 0, buff.Length);
			ns.Flush();

			byte[] getByte;
			StringBuilder sb = new StringBuilder();

			while (ns.DataAvailable)
			{
				getByte = new byte[client.ReceiveBufferSize];
				int size = ns.Read(getByte, 0, getByte.Length);
				sb.Append(System.Text.Encoding.ASCII.GetString(getByte));
			}
			return sb.ToString();
		}


	}
}