404 motivation not found | t_ishidaのブログ

12月/07

31

なんちゃってWebサーバー

能書き

昨日のはWebサーバーもどきでしたが、今日のは「なんちゃって」って、

言える程度に実装してあります。

基本的に実用は無理だし、これを使ってなんか有っても知りません。

Webサーバーとして、致命的にできないこと

  • POSTが受け取れない(をい
  • 接続がラッシュすると多分死ぬ
    • 多分二つに分けて、folkする形にしないとだめ。
  • 画像とかは基本的に無理
    • CGI側でヘッダを自分で作って、ストリームを流せばあるいは

ソケット通信周りとかは普段やらないので、

専門的な人から見たら結構アレなプログラムかも知れません。

なので、突っ込みは歓迎。

いろんなところから、ソースは切った貼ったしてます。

まあ、とりあえずCGIってのがどんなものか?

って言うのは、PHPの話、昨日今日の話で、

どんな事をしているのかが見えやすくなったんじゃないかと。

残る謎としては、PHPの知識の整理からはじめたはずなのに、

なんでWebサーバーをPerlでプログラムしているのか?

と言うところ。

遊び方

  1. 昨日のWebサーバーと同じように、index.htmlとかindex.cgiとかがあるディレクトリに保存する
  2. こいつをキックする。
  3. キックすると永久ループしてると思うんで、http://localhost/index.htmlとかってブラウザに入れてみる。
  4. 画面にindex.htmlが出てきて嬉しいね。
  5. 画面にindex.cgiが出てきて嬉しいね。

ソース

use strict;
use Socket;
##ソケットの準備
socket(CLIENT_WAITING, PF_INET, SOCK_STREAM, 0);
setsockopt(CLIENT_WAITING, SOL_SOCKET, SO_REUSEADDR, 1);
bind(CLIENT_WAITING, pack_sockaddr_in(80, INADDR_ANY));
##監視
listen(CLIENT_WAITING, SOMAXCONN);
while (1){
my $paddr = accept(CLIENT, CLIENT_WAITING);

##繋がる
my ($client_port, $client_iaddr) = unpack_sockaddr_in($paddr);
my $client_hostname = gethostbyaddr($client_iaddr, AF_INET);
my $client_ip = inet_ntoa($client_iaddr);
select(CLIENT);
$|=1;
select(STDOUT);
##昨日のはこの辺りから

##CLIENTのコマンドを受け取る
my $arg = <CLIENT>;
my ( $cmd, $query ) = split(/ +/,$arg);
if( $query =~/^([^?]+)\?(.+)$/ ) {
$query = $1;
$ENV{'QUERY_STRING'} = $2;
}
$query =~s/^\///;
$query =~/\.([^\.]+)$/;
my %cgi_exts = ( 'cgi' => 1 , 'CGI' => 1 );
if( !$cgi_exts{$1} ) {
##htmlをヘッダと共に返す
print CLIENT "HTTP/1.0 200 OK\r\n";
print CLIENT "Content-type: text/html\n\n";
open F , "$query";
print CLIENT <F>;
close F;
} else {
##CGIを実行して返す
open F , $query; my @buf = <F>; close F;
## #!を読み取ってるのは、Windows環境向けね。
shift(@buf) =~/#!(.+)$/;

## バッククォートでコマンドを実行すると標準出力を横取りできるの。
print CLIENT `$1 $query`;
}
close CLIENT;
}

ソース2

こちらはIO::Socketを使ってます。

やってることは一緒です。

専門家じゃないので、こちらの方が有りがたい。

#!/usr/local/bin/perl -w
use IO::Socket;
use strict;
while(1){
my $sock0 = new IO::Socket::INET(
Listen=>5,
LocalAddr=>'localhost',
LocalPort=>80,
Proto=>'tcp',
Reuse=>1);

die "IO::Socket : $!" unless $sock0;
my $sock = $sock0->accept();
my $param = <$sock>;
my ( $cmd, $query ) = split(/ +/,$param);
if( $query =~/^([^?]+)\?(.+)$/ ) {
$query = $1;
$ENV{'QUERY_STRING'} = $2;
}
$query =~s/^\///;
$query =~/\.([^\.]+)$/;
my %cgi_exts = ( 'cgi' => 1 , 'CGI' => 1 );
if( !$cgi_exts{$1} ) {
print $sock "HTTP/1.0 200 OK\r\n";
print $sock "Content-type: text/html\n\n";
open F , "$query";
print $sock <F>;
close F;
} else {
open F , $query; my @buf = <F>; close F;
shift(@buf) =~/#!(.+)$/;
print $sock `$1 $query`;
}
close($sock);
close($sock0);
}
Share and Enjoy:
  • Digg
  • del.icio.us
  • Google Bookmarks
  • Tumblr
  • email
  • Facebook
  • FriendFeed

RSS Feed

コメントはまだありません。

Leave a comment!

<< 正月分の日記

Webサーバーもどきを作ってみる >>

Find it!

Theme Design by devolux.org

Tag Cloud