免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3117 | 回复: 0
打印 上一主题 下一主题

Perl Socket Programming-Multiplex with IO::Poll [复制链接]

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2003-06-24 13:40 |只看该作者 |倒序浏览
以下資料為本人閱讀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。


  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.   #沒資料讀取表示STDIN已經終止,否則將資料放入to_socket buffer中
  37.     $stdin_done++ unless sysread(STDIN,$to_socket,2048,length $to_socket);
  38.     }
  39.     elsif($handle eq $socket){
  40.   # 沒資料讀取表示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為真且已經沒有資料送出至$socket了,則將$socket 關閉
  84.   $socket->;shutdown(1) if $stdin_done and !length($to_socket);
  85. }
复制代码

[ 本帖最后由 apile 于 2006-11-9 08:55 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP