http最高
先日Fedora Core 2 LinuxのDVDイメージをダウンロードしようとして,そのファイルサイズが32bitを越えていることに気付いた.
例えば以下はKDDI研究所のミラーサイトであるが,HTTPでこのファイルにアクセスしたときの挙動が面白い.
http://ftp.kddilabs.jp/Linux/packages/fedora/core/2/i386/iso/
ftp://ftp.kddilabs.jp/Linux/packages/fedora/core/2/i386/iso/
HTTP/1.1 301 Moved Permanently
Date: Wed, 26 May 2004 16:12:01 GMT
Server: Apache
Location: ftp://ftp.kddilabs.jp/Linux/packages/fedora/core/2/i386/iso/FC2-i386-DVD.iso
現状httpサーバ/クライアントともに(4GB)2GBを越えるファイルを扱えるものは意外と少ない.それを考えるとこのリダイレクトは妥当と言えるかもしれないが,Internet Explorer 6.0はFTPでもファイルサイズの下位32bitしか見ないようで結局ダウンロードに失敗する*1.世の中なかなかうまく行かないものだ.ちなみにFFFTPではダウンロードに成功している.
なお,HTTPによるダウンロードに関していくらか実験してみた結果が以下である.
- System.Net.WebClient (.NET Framework 1.1)
- "Content-Length"を下位32bitしか見ない.負値になったら即切断.
- Internet Explorer 6.0
- "Content-Length"の下位32bitしか見ない.負値になったら即切断.
- Irvine 1.1.1
- ダウンロードサイズが2GBを越えてから表示が負値になる.4GBを越えると表示が-1になる.ダウンロードが終わる(向こうから切断される)とダウンロードが失敗したと解釈される(そしてデフォルトでは再びダウンロードを開始する).
- Mozilla 1.8a1
- ダウンロードサイズが2GBを越えてから表示が負値になる.4GBを越えたあたりでダウンロードが停止する.
4GBを越えるデータを扱えるhttpdサーバだが,探すのが面倒なのでC#でごく簡単なものを作ってみた.以下,http的には無茶苦茶だがとりあえず山のような"!"を返すプログラムである.
>
using System;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Globalization;
using System.Text;static void Server()
{
IPAddress addr = IPAddress.Loopback;
System.Net.Sockets.TcpListener serv = new System.Net.Sockets.TcpListener( addr, 80 );
serv.Start();
while(true)
{
using( TcpClient client = serv.AcceptTcpClient() )
{
using( NetworkStream ns = client.GetStream() )
{
try
{
StreamReader sr = new StreamReader( ns );// 全体のサイズ
long dataSize = 0x110000000;// 一度に出力するデータのサイズ
int dataBlock = 4*1024*1024;while(true)
{
string line = sr.ReadLine();
if( line == "" )
{
break;
}
}DateTimeFormatInfo dtf = CultureInfo.InvariantCulture.DateTimeFormat;
string msg = string.Format(
"HTTP/1.1 200 OK\r\n" +
"Date: {0}\r\n" +
"Server: TestServer\r\n" +
"Content-Type: text/plain\r\n" +
"Content-Length: {1}\r\n" +
"\r\n",
DateTime.Now.ToString(dtf.RFC1123Pattern, CultureInfo.InvariantCulture),
dataSize );byte[] data = Encoding.ASCII.GetBytes( new string('!',dataBlock) );
StreamWriter sw = new StreamWriter( ns );
sw.Write( msg );
sw.Flush();
for( long i = 0; i < dataSize / dataBlock; ++i )
{
ns.Write( data, 0, data.Length );
}
}
catch(Exception)
{
}
}
}
}
}
*1:最初の200MBちょっとしかダウンロードしない