お知らせ

電子会議

ライブラリ

パレット

Delphi FAQ検索

Delphi FAQ一覧

サンプル蔵





FDelphi FAQ
16番会議室「玉石混淆みんなで作るSample蔵」に寄せられたサンプル

"TServerSocketでブロッキング通信"

この発言に対し以下のコメントが寄せられています
#00987 KeY さん RE:TServerSocketでブロッキング通信

みなさんこんにちは、KeYです。 TServerSocketでstThreadBlockingを使用するときのサンプルです。 素朴なHTTPデーモンを作ってみました。 使い方は、 1.アプリケーションの新規作成を選ぶ。 2.フォームにServerSocketを張り付ける。 3.Unit1.pasを入れ替える。 4.フォームのOnCreateとOnDestroy、 ServerSocket1のOnGetThreadを関連づける 5.Constで定義しているポート番号と、ドキュメントルートのディレクトリ、 デフォルトのファイルを確認・変更する。 6.末尾で定義しているContent-Typeを確認・変更する。 7.ドキュメントルートのディレクトリにファイルを置く。 で実行。 これでブラウザから http://127.0.0.1:8080/ などでアクセス可能に。 RFCなど読んだことがないので馬鹿な間違いをしているかもしれませんが とりあえず動きました。 なんかまずい所があったら添削願います。 m(_ _)m あ、D4とD5で確認しました。それと、TServerSocketを使っているので Proffesional版以上になるのでしょうか。 //----Unit1.pasここから unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ScktComp; type TForm1 = class(TForm) ServerSocket1: TServerSocket; procedure ServerSocket1GetThread(Sender: TObject; ClientSocket: TServerClientWinSocket; var SocketThread: TServerClientThread); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private { Private 宣言 } public { Public 宣言 } end; TTinyHttpdThread = class(TServerClientThread) private { Private 宣言 } protected procedure ClientExecute; override; end; const RootDir='c:\Delphi\Httpd\Root'; PortNo=8080; DefaultDoc='index.html'; Response403='HTTP/1.0 403 Forbidden'#13#10+ 'Content-Type: text/plain'#13#10#13#10'Error 403 Forbidden'; Response404='HTTP/1.0 404 Not Found'#13#10+ 'Content-Type: text/plain'#13#10#13#10'Error 404 Not Found'; var Form1: TForm1; implementation {$R *.DFM} var ContentTypes: TStrings; procedure TForm1.FormCreate(Sender: TObject); begin ServerSocket1.Port:=PortNo; ServerSocket1.ServerType:=stThreadBlocking; ;ServerSocket1.Active:=True; end; procedure TForm1.FormDestroy(Sender: TObject); begin if ServerSocket1.Active then begin ServerSocket1.Active:=False; end; end; procedure TForm1.ServerSocket1GetThread(Sender: TObject; ClientSocket: TServerClientWinSocket; var SocketThread: TServerClientThread); begin SocketThread:=TTinyHttpdThread.Create(False, ClientSocket); end; { TTiniHttpdThread } procedure TTinyHttpdThread.ClientExecute; var Stream: TWinSocketStream; Buffer: array[0..4095] of Char; GetSize: Integer; HttpReq: TMemoryStream; HttpReqStr: TStrings; s: string; i: Integer; SendFile: TFileStream; SendFileExt: string; SendHeader: string; ContentType: string; begin HttpReq:=TMemoryStream.Create; HttpReqStr:=TStringList.Create; try //このループはお決まりのもの while (not Terminated) and ClientSocket.Connected do begin try //ソケットストリームの作成 Stream:=TWinSocketStream.Create(ClientSocket, 500); try //受信可能状態になるのを待つ if Stream.WaitForData(60000) then begin //リクエストを全部読んでTMemoryStreamに保存 // 本当はセキュリティホールになるのでやってはいけない HttpReq.Clear; GetSize:=Stream.Read(Buffer, sizeof(Buffer)); while GetSize>0 do begin HttpReq.Write(Buffer, GetSize); GetSize:=Stream.Read(Buffer, sizeof(Buffer)); end; //TStringsにコピー HttpReq.Seek(0, soFromBeginning); HttpReqStr.LoadFromStream(HttpReq); //GETメソッドか? if CompareText( Copy(HttpReqStr.Strings[0], 1, 4),'GET ')=0 then begin //'GET 'を削除 s:=Copy(HttpReqStr.Strings[0], 5, Length(HttpReqStr.Strings[0])); s:=Trim(s); //ディレクトリ部分だけ抜き出す if Pos(' ', s)>0 then s:=Copy(s, 1, Pos(' ', s)-1); //'/'を'\'に変更 for i:=1 to Length(s) do begin if (s[i]='/') then s[i]:='\'; end; //ルートディレクトリを付ける s:=rootdir+s; //最後がフォルダならデフォルトファイルを追加 if s[Length(s)]='\' then s:=s+DefaultDoc; //ファイルをオープン // CGI引数付きのGETメソッドはここで失敗する // また引数なしのCGIプログラムはそのまま // ファイルを渡してしまう try SendFile:=TFileStream.Create( s, fmOpenRead or fmShareDenyWrite ); except //失敗したら404のエラー SendFile:=nil; s:=Response404; Stream.Write(s[1], Length(s)); end; if Assigned(SendFile) then begin try //拡張子を取得 SendFileExt:=ExtractFileExt(s); //'.'を取り除く Delete(SendFileExt,1,1); //Content-Typeを決定 ContentType:=ContentTypes.Values[s]; //設定なし if s='' then ContentType:='application/octet-stream'; //最低限のヘッダ SendHeader:='HTTP/1.0 200 '#13#10+ 'Content-Type: '+ContentType+ #13#10#13#10; //ヘッダ送信 Stream.Write(SendHeader[1], Length(SendHeader)); //ファイルを送信 GetSize:=SendFile.Read(Buffer, sizeof(Buffer)); while GetSize>0 do begin Stream.Write(Buffer, GetSize); GetSize:=SendFile.Read(Buffer, sizeof(Buffer)); end; finally SendFile.Free; end; end; end else begin //GETメソッド以外には対応していません s:=Response403; Stream.Write(s[1], Length(s)); end; end; finally //ソケットストリームを破棄 Stream.Free; //ソケットをクローズ ClientSocket.Close; end; except HandleException; end; end; finally HttpReq.Free; HttpReqStr.Free; end; end; initialization ContentTypes:=TStringList.Create; ContentTypes.Add('HTML=text/html'); ContentTypes.Add('HTM=text/html'); ContentTypes.Add('JPEG=image/jpeg'); ContentTypes.Add('JPG=image/jpeg'); ContentTypes.Add('GIF=image/gif'); finalization ContentTypes.Free; end. //----Unit1.pasここまで 99/12/4(Sat) 02:25am VEJ04660 KeY Original document by KeY 氏 ID:(VEJ04660)



ここにあるドキュメントは NIFTY SERVEの Delphi Users' Forum の16番会議室「玉石混淆みんなで作るSample蔵」に投稿されたサンプルです。これらのサンプルはボーランド株式会社がサポートする公式のものではありません。また、必ずしも動作が検証されているものではありません。これらのサンプルを使用したことに起因するいかなる損害も投稿者、およびフォーラムスタッフはその責めを負いません。使用者のリスクの範疇でご使用下さい。

Copyright 1996-2002 Delphi Users' Forum