![Rank: 9](images/default/star_level3.gif) ![Rank: 9](images/default/star_level3.gif) ![Rank: 9](images/default/star_level1.gif)
- UID
- 2031431
- 威望
- 27 点
- 金钱
- 2 金币
- 点卡
- 10 点
|
1#
发表于 2003-12-10 02:14
| 只看该作者
[转帖]為什麼要用IO::Poll?
作者:apile
因為使用IO::Select時候,因為其儲存handle是存在。。。。。。
以下資料為本人閱讀Nework Programming With Perl的記要..
有興趣的自己研究研究...
------------------------------------------------------------------------------
date: 2003/06/22
IO: oll的使用說明:
在5.6版本的時候開始發展,功能完整的版本為0.04版。所以要注意的是IO: oll版本一定要是0.04以上。
為什麼要用IO: oll?因為使用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){
- #?#93;資料讀取表示STDIN已經終止,否則將資料放入to_socket buffer中
- $stdin_done++ unless sysread(STDIN,$to_socket,2048,length $to_socket);
- }
- elsif($handle eq $socket){
- # ?#93;資料讀取表示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為真且已經?#93;有資料送出至$socket了,則將$socket 關?#93;
- $socket->shutdown(1) if $stdin_done and !length($to_socket);
- }
复制代码 |
哈哈哈!!!!你的IP是不是 ?我都知道了!!! |
|