Chinaunix
标题:
Perl Socket Programming-Multiplex with IO::Poll
[打印本页]
作者:
apile
时间:
2003-06-24 13:40
标题:
Perl Socket Programming-Multiplex with IO::Poll
以下資料為本人閱讀Nework Programming With Perl的記要..
有興趣的自己研究研究...
=============================================
date: 2003/06/22
IO::Poll的使用說明:
在5.6版本的時候開始發展,功能完整的版本為0.04版。所以要注意的是IO::Poll版本一定要是0.04以上。
為什麼要用IO::Poll?因為使用IO::Select時候,因為其儲存handle是存在bit vector裡面,因此必須針對所有監控中的Handle一個一個去Scan,找出可以Read/Write的handle。因此在效能的Issue上,當遇到大量的handle需要監控時,就會產生效能上的降低。而IO::Poll的機制則不是這麼回事,他同樣可以監控大量的HANDLE,但是利用array儲存這些handle,因為array的儲存機制,並不同於bit vector,並不需要一個一個去Scan這些handle,所以在效能上比較好。
IO::Poll只需要一個Object就可以處理所有的handle,透過bitmask將Event傳給被監控的Handle,一旦符合需求,可以從handle中取出。
IO::Poll接受的Event(mask):
可讀的
POLLIN:一般與有Priority的資料
POLLRDNORM:一般的資料
POLLRDBAND:有Priority的資料
POLLPRI:特別高的Priority
可寫的
POLLOUT:一般與有Priority的資料
POLLWRNORM:一般的資料
POLLWRBAND:有Priority的資料
有錯誤的
POLLHUP:HangUp發生
POLLNVAL:handle不合法
POLLERR:有Error發生,如果是Socket可用sockopt(SO_ERROR)取得Error內容
IO::Poll的method
1.$poll=IO::Poll->;new():產生IP::Poll的Object
2.$mask=$poll->;mask($handle,[$mask])
取得或設定目前handle的 event bitsmask,如果mask沒給,則目前的設定值回傳。如果有給mask則將該mask設定給該handle。如果mask為0,則從list將該handle移除。所有的handle預設都會監控(POLLNVAL、POLLERR、POLLHUP)。
3.$poll->;remove($handle)
同$poll->;mask($handle,0);
4.$events=$poll->;poll([$timeout])
等候有任何一個監控中的handle可以被讀取或寫入。回傳Event Type。
5.@handles=$poll->;handles([$mask])
取出符合mask的handles。
6.$mask = $poll->;events($handle)
取得$handles的所有mask。
#!/usr/bin/perl
# file : test.pl
# usage: test.pl [host] [port]
# 利用IO::Poll達到多工的技術
#--加載module
use strict;
use IO::Socket;
#--引用後面的constant
use IO::Poll qw( POLLIN POLLOUT POLLERR POLLHUP);
use Errno qw(EWOULDBLOCK);
#--設定Buffer的最大值
use constant MAXBUF =>;8192;
#--忽略掉HANG HUP的Signal
$SIG{PIPE} = 'IGNORE';
#--設定全域變數,兩個buffer兩個flag
my ( $to_stdout,$to_socket,$stdin_done,$sock_done);
#--取得 host and port
my $host = shift or die "Usage: test.pl host [port]\n";
my $port = shift || 'echo';
#--建立Socket
my $socket = IO::Socket::INET->;new("$host:$port") or die $@;
my $poll = IO::Poll->;new() or die "Can't create IO::Poll object";
#--一開始先將STDIN與$socket放入list中,並將其mask設定為POLLIN準備讀取。
$poll->;mask(\*STDIN =>; POLLIN);
$poll->;mask($socket =>; POLLIN);
#--設定標準輸出與$socket為noblocking mode
$socket->;blocking(0); # turn off blockingon the socket
STDOUT->;blocking(0); # and on STDOUT
#--main loop,$poll->;handles會回傳所有正在監控中的handle
while($poll->;handles){
#--等候直到有事件符合
$poll->;poll;
# 處理可讀取的事件
for my $handle ($poll->;handles(POLLIN|POLLHUP|POLLERR)){
if($handle eq \*STDIN){
#沒資料讀取表示STDIN已經終止,否則將資料放入to_socket buffer中
$stdin_done++ unless sysread(STDIN,$to_socket,2048,length $to_socket);
}
elsif($handle eq $socket){
# 沒資料讀取表示Socket已經讀取完畢,否則將資料附入to_stdout buffer中
$sock_done++ unless sysread($socket,$to_stdout,2048,length $to_stdout);
}
}
# 處理可寫入的事件
for my $handle ($poll->;handles(POLLOUT|POLLERR)){
if($handle eq \*STDOUT){
my $bytes = syswrite(STDOUT,$to_stdout);
# 假若不是EWOULDBLOCK,表示真的有Error發生,所以才無法寫入
unless ($bytes){
next if $! == EWOULDBLOCK;
die "write to stdout failed: $!";
}
# 如果發生Partial Write將已經寫出的先清掉。
substr($to_stdout,0,$bytes) = '';
}
elsif($handle eq $socket){
my $bytes = syswrite($socket,$to_socket);
unless ($bytes){
next if $! == EWOULDBLOCK;
die "write to socket failed: $!";
}
substr($to_socket,0,$bytes) = '';
}
}
} continue {
# 每次While loop執行時都會執行到這兒
# 先設定三個bitmask為0,表示將從list中將該handle移除
my ($outmask,$inmask,$sockmask) = (0,0,0);
# 設定stdout的mask,假如有資料要寫出去,則將其mask設為可寫(POLLOUT)
$outmask = POLLOUT if length $to_stdout >; 0;
# 當 to_socket的資料長度比MAXBUF大、或socket已經完結
# 或stdin已經完結,都不成立時,則設定STDIN可讀取。
$inmask = POLLIN unless length $to_socket >;= MAXBUF
or ($sock_done || $stdin_done);
# 假如有資料要寫出去,設定$socket為POLLOUT(待寫)
$sockmask = POLLOUT if length $to_socket>;0;
# 同STDIN定義,但是|=表示附加上去,因為Socket可以同時讀寫
$sockmask |= POLLIN unless length $to_stdout>;=MAXBUF or $sock_done;
# 設定STDIN、STDOUT、Socket三個handle的bitmask
$poll->;mask(\*STDIN =>; $inmask);
$poll->;mask(\*STDOUT=>; $outmask);
$poll->;mask($socket =>; $sockmask);
# 如果$stdin_done為真且已經沒有資料送出至$socket了,則將$socket 關閉
$socket->;shutdown(1) if $stdin_done and !length($to_socket);
}
复制代码
[
本帖最后由 apile 于 2006-11-9 08:55 编辑
]
欢迎光临 Chinaunix (http://bbs.chinaunix.net/)
Powered by Discuz! X3.2