免费注册 查看新帖 |

Chinaunix

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

又有一个select或fork都不好搞的问题! [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2003-05-09 16:23 |只看该作者 |倒序浏览
问题产生在win32系统下,linux没问题。
请看举例代码:
#!/usr/bin/perl
use IO::Select;

my $select = IO::Select->;new(\*STDOUT,\*STDIN);

while (1) {
my @ready = $select->;can_read;

foreach  (@ready) {
  if ($_ eq \*STDIN) {
        $ff = <$_>;;
  } else {
        print $ff;
}
}
}

这个代码分别产生两个Select一个负责读,一个负责写。
这个代码在win32下无法工作。

我用这个代码的目的就是测试我刚做的UDPChat
如果在客户端将Recv和Send放在一起,将出问题。
我测试select或fork都不能正确工作。

我是用在Console下做的,如果用GUI的化...我不知道如何fork。其实要求不复杂。有没有人有example

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
2 [报告]
发表于 2003-05-11 21:24 |只看该作者

又有一个select或fork都不好搞的问题!

一個multiplexed client

$!/usr/bin/perl

use strict;
use IO::Select;
use IO::Select;
use constant BUFSIZE=>;1024;

my $host = shift or die "Usagexx.pl host [port]\n";
my $port  = shift || 'echo';

my $socket= IO::Socket::INET->;new("$hostport" or die $@;
my $readers = IO::Select->;new or die "can't create IO::Select read object";
$readers->;add(\*STDIN);
$readers->;add($socket);
my $buffer;
while(1){
  my @ready = $readers->;can_read;
  for my $handle (@ready){
    if($handle eq \*STDIN){
        if(sysread(STDIN,$buffer,BUFSIZE)>; 0){
            syswrite($socket,$buffer);
        }else{
            $socket->;shutdonw(1);
        }
    }

    if($handle eq $socket){
       if(sysread($socket,$buffer,BUFSIZE) >;0){
           syswrite(STDOUT,$buffer);
       }else{
           warn "Connection close by foreign host.\n";
           exit 0;
       }
  }
}

這是個以tcp為例的代碼...
書上有提到..用<>;速度會比較慢.
.如果為了效能起見..用sysread、syswrite比較好..
另外udp用的是send與recv..跟..tcp用的不一樣哩...
#!/usr/bin/perl
use strict;
use IO::Socket;
use IO::Select;
use IO::Getline;

use constant MAS_MSG_LEN =>; 5000;
use constant TIMEOUT =>; 2;
use constant MAX_RETRIES =>; 5;

my %PENDING; # hash of requests indexed by sequence number
use constant REQUESTs =>; 0; # with these two fields
use constant TRIES =>; 1;

# keep track of outgoing and incoming sequence numbers
my $seqout = 0;
my $seqin = 0;

my $host = shift||'localhost';
my $port = shift || 'echo';
my $sock = IO::Socket::INET->;new(Proto=>;'udp', PeerAddr=>;"$hostport"
        or die $@;

my $select = IO::Select->;new($sock,\*STDIN);
my $stdin = IO::Getline->;new(\*STDIN);

LOOP:
while(1){
    my @ready = $select->;can_read(TIMEOUT);
    for my $handle (@ready){
       if($handle eq \*STDIN){
          my $length = $stdin->;getline($_) || last LOOP;
          next unless $length>;0;
          chomp;
          send_message($seqout++,$_);
       }
       if($handle eq $sock){
         my $data;
         $sock->;recv($data,$MAX_MSG_LEN) || die "recv() : $!\n";
         receive_message($data);
       }
    }
    # handle any leftover messges on timeout events
    do_retries() unless @ready;
}

sub send_message{
   my ($sequence,$msg) = @_;
   # send the message
   $sock->;send("$sequencemsg" or die "send(): $! \n";
   # mark this as pending
   $PENDING{$sequence}[$REQUEST] = $msg;
   $PENDING{$sequenct}[TRIES]++;
}

sub receive_message{
  my $message = shift;
  my($sequence,$msg) = $message=~ /^(\d+).*)/
    || return wrarn "bad format message '$message'!\n";
  #die we ask for this
  unless($PENDING{$sequence}){
    warn "Discarding duplicate message seqno = $sequence\n";
    return;
  }
  # warn about out of order messages
  warn "Out of order message seqno = $sequence\n" if $sequence <$seqin;
  
  # print result
  print $PENDING{$seqence}[REQUEST],' =>; ',',$msg,"\n";
  
  #remember last sequence number, and remove message from pending
  $seqin = $sequence;
  delete $PENDING{$sequence};
}

sub do_retries{
    for my $seq (keys %PENDING){
       if($PENDING{$seq}[TRIES] >;= MAX_RETRIES){
           warn "$seq: too many retries. Giving up.\n";
           delete $PENDING{$seq};
           next;
       }
       warn "$seq:retrying...\n";
       send_message($seq,$PENDING{$seq}[REQUEST]);
    }
}

看看對你有沒有幫助....

论坛徽章:
0
3 [报告]
发表于 2003-05-12 13:17 |只看该作者

又有一个select或fork都不好搞的问题!

你给的代码也不能在win32下运行。

我是指第一个带有STDIN的代码

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
4 [报告]
发表于 2003-05-13 13:25 |只看该作者

又有一个select或fork都不好搞的问题!

Sorry..我沒有在windows環境下寫過Perl..

STDIN、STDOUT是Perl標準輸入與輸出的sign.....
以語法來說應該沒錯才對....會不是是因為你用<$_>;試圖從
標準輸入中取資料的關係?
因為用到IO::Select時候..書上是建議少用<>;、read、open等等..
儘量用syswrite與sysread..
如果還是不行..加個
use English;
可以用英文取代一些特殊符號...也許有用...
另外我給的代碼..有些地方不小心Keyin錯誤..所以要做點debug..
再不行...我也不曉得了...

论坛徽章:
0
5 [报告]
发表于 2003-05-13 15:39 |只看该作者

又有一个select或fork都不好搞的问题!

代码我在Linux测试可以的。

在Win32下就跑不起来。真实头痛...

我还是找人用Visual C写一个Client吧...
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP