返回列表 回复 发帖

[转帖]為什麼要用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。
  1. #!/usr/bin/perl
  2. # file : test.pl
  3. # usage: test.pl [host] [port]
  4. # 利用IO::Poll達到多工的技術
  5. #--加載module
  6. use strict;
  7. use IO::Socket;
  8. #--引用後面的constant
  9. use IO::Poll qw( POLLIN POLLOUT POLLERR POLLHUP);
  10. use Errno qw(EWOULDBLOCK);
  11. #--設定Buffer的最大值
  12. use constant MAXBUF =>8192;
  13. #--忽略掉HANG HUP的Signal
  14. $SIG{PIPE} = 'IGNORE';
  15. #--設定全域變數,兩個buffer兩個flag
  16. my ( $to_stdout,$to_socket,$stdin_done,$sock_done);
  17. #--取得 host and port
  18. my $host = shift or die "Usage: test.pl host [port]\n";
  19. my $port = shift || 'echo';
  20. #--建立Socket
  21. my $socket = IO::Socket::INET->new("$host:$port") or die $@;
  22. my $poll = IO::Poll->new() or die "Can't create IO::Poll object";
  23. #--一開始先將STDIN與$socket放入list中,並將其mask設定為POLLIN準備讀取。
  24. $poll->mask(\*STDIN => POLLIN);
  25. $poll->mask($socket => POLLIN);
  26. #--設定標準輸出與$socket為noblocking mode
  27. $socket->blocking(0); # turn off blockingon the socket
  28. STDOUT->blocking(0);  # and on STDOUT
  29. #--main loop,$poll->handles會回傳所有正在監控中的handle
  30. while($poll->handles){
  31. #--等候直到有事件符合
  32.   $poll->poll;
  33.   # 處理可讀取的事件
  34.   for my $handle ($poll->handles(POLLIN|POLLHUP|POLLERR)){
  35.     if($handle eq \*STDIN){
  36.   #?#93;資料讀取表示STDIN已經終止,否則將資料放入to_socket buffer中
  37.     $stdin_done++ unless sysread(STDIN,$to_socket,2048,length $to_socket);
  38.     }
  39.     elsif($handle eq $socket){
  40.   # ?#93;資料讀取表示Socket已經讀取完畢,否則將資料附入to_stdout buffer中
  41.    $sock_done++ unless sysread($socket,$to_stdout,2048,length $to_stdout);
  42.     }
  43.   }
  44.   # 處理可寫入的事件
  45.   for my $handle ($poll->handles(POLLOUT|POLLERR)){
  46.      if($handle eq \*STDOUT){
  47.        my $bytes = syswrite(STDOUT,$to_stdout);
  48.      # 假若不是EWOULDBLOCK,表示真的有Error發生,所以才無法寫入
  49.        unless ($bytes){
  50.           next if $! == EWOULDBLOCK;
  51.           die "write to stdout failed: $!";
  52.        }
  53.      # 如果發生Partial Write將已經寫出的先清掉。
  54.        substr($to_stdout,0,$bytes) = '';
  55.      }
  56.      elsif($handle eq $socket){
  57.        my $bytes = syswrite($socket,$to_socket);
  58.        unless ($bytes){
  59.           next if $! == EWOULDBLOCK;
  60.           die "write to socket failed: $!";
  61.        }
  62.        substr($to_socket,0,$bytes) = '';
  63.      }
  64.   }
  65. } continue {
  66.   # 每次While loop執行時都會執行到這兒
  67.   # 先設定三個bitmask為0,表示將從list中將該handle移除
  68.   my ($outmask,$inmask,$sockmask) = (0,0,0);
  69.   # 設定stdout的mask,假如有資料要寫出去,則將其mask設為可寫(POLLOUT)
  70.   $outmask = POLLOUT if length $to_stdout > 0;
  71.   # 當 to_socket的資料長度比MAXBUF大、或socket已經完結
  72.   # 或stdin已經完結,都不成立時,則設定STDIN可讀取。
  73.   $inmask = POLLIN unless length $to_socket >= MAXBUF
  74.                       or ($sock_done || $stdin_done);
  75.   # 假如有資料要寫出去,設定$socket為POLLOUT(待寫)
  76.   $sockmask = POLLOUT if length $to_socket>0;
  77.   # 同STDIN定義,但是|=表示附加上去,因為Socket可以同時讀寫
  78.   $sockmask |= POLLIN unless length $to_stdout>=MAXBUF or $sock_done;
  79.   # 設定STDIN、STDOUT、Socket三個handle的bitmask
  80.   $poll->mask(\*STDIN => $inmask);
  81.   $poll->mask(\*STDOUT=> $outmask);
  82.   $poll->mask($socket => $sockmask);
  83.   # 如果$stdin_done為真且已經?#93;有資料送出至$socket了,則將$socket 關?#93;
  84.   $socket->shutdown(1) if $stdin_done and !length($to_socket);
  85. }
复制代码
哈哈哈!!!!你的IP是不是?我都知道了!!!
返回列表