线程用来为 GUI 服务的,没啥别的意思。
# POE 自己就够强了,能够解决多线索的 SMPP 通讯协议转发问题
use Win32::GUI;use Win32 ();use Win32::GUI::Loft::Design;# Loft 实在是 windows perl 的 MVC 的居家必备
use Data::HexDump;# 用来在小黑窗滚动打印那些看来很专业的 hex 数据包 dump
use Time::HiRes;# 没啥用处,喜欢精确的个性使然
use POE qw(Component::Server::TCP Component::Client::TCP Filter::Stream Filter::Block );# 发现 Filter  Block 是个惊喜,用来解决数据包打头的大小字段的打包解包问题,pack 在这点上还是不够 handy

my $fileWindow = "C:\\test.gld";    #You created this using The GUI Loft
my $objDesign = Win32::GUI::Loft::Design->newLoad($fileWindow)  or die("Could not open window file ($fileWindow)");my $win = $objDesign->buildWindow()  or die("Could not build window ($fileWindow)");# 从设计好的 .gld 文件来重新建立窗口

my $min = 0;my $icon = new Win32::GUI::Icon('c:\\pxperl\\bin\\pxperl.ico');my $ni = $win->AddNotifyIcon(   -name   => "NI", -id => 1,                                -icon   => $icon,                                -tip    => "短信");# 再来个托盘最小化图标,弄得专业一点

$win->Show();Win32::GUI::Dialog();# 窗口上现在应该有:开始、最小化(hide)、退出三个按钮,老板不挑剔的话已经足够了

sub ::winmsg_Terminate {    return (-1);}sub ::btnhide_Click {    definedmy $win = $Win32::GUI::Loft::window{winmsg} ) or return (1);    $win->Disable() unless $min;    $win->Hide() unless $min;    $min=1;    return (1);}sub ::btnquit_Click {    return (-1);}# 返回 -1 就是最小化了

sub NI_Click {    definedmy $win = $Win32::GUI::Loft::window{winmsg} ) or return (1);    if ($min) {        $win->Enable(); $win->Show(); $min=0return(1);    } else {        $win->Disable(); $win->Hide(); $min=1return(1);    };}# 从托盘怎么唤醒小窗口

sub ::btnok_Click {    definedmy $win = $Win32::GUI::Loft::window{winmsg} ) or return (1);    async {        my ( $retrytime, $seq, $bnd, %clients= ( 1, 16, 0, 0, undef);        POE::Component::Server::TCP->new (            Port => 19231,            ClientInput => sub {                my ($kernel, $heap, $input= @_[ KERNEL, HEAP, ARG0];                warn $input;                $kernel->yield(q(shutdown)) if ($input =~ /quit/);                $kernel->stop() if ($input =~ /kill/);            },        );       # 用 telnet 遥毙程序,故作神秘
        sub enc {            my $stuff = shift;            substr($$stuff, 0, 0= pack q(N), 4+length($$stuff);            warn HexDump $$stuff;            return;        };        sub dec {            my $stuff = shift;            return unless length($$stuff>= 4;            return unpack(q(N), $$stuff);        };       # 前面说的 pack 的软肋就在这里用下面的 Filter::Block 的两个打包拆包处理器解决了
        POE::Component::Server::TCP->new (            Port            => 1314,            ClientFilter    => ["POE::Filter::Block", LengthCodec => [\&enc, \&dec]],            ClientConnected => sub {            },            ClientDisconnected => sub {                my $clid = $_[SESSION]->ID();                delete $clients{$clid};                warn "smpp client $clid stopped";            },            # 客户退出例行告警,没啥实际用处,可以拓展成其他形式的意外 alert
            ClientInput     => sub {                my ($kernel, $heap, $input= @_[ KERNEL, HEAP, ARG0];                my $cmd = unpack 'N', substr($input, 4, 4);                if ( $cmd == 0x00000004 ) {                    my (undef, undef, $subseq, $subfrom, $subto, $esm, $code, $body=                        unpack q(N2xx![N]N x(x2Z*)2Cx6CxC/A*), $input;                    # 不懂就赶快去看 packtut 和 Net::SMPP 两个 perldoc
                    $heap->{client}->put(                        pack q(N3 Z*), 0x80000004, 0, $subseq, q(1a2b3c4d));                    #  成功发送的 ack 发送出去了,其实不是这里干的,而是在下面用 proxysub 真的在发送短信,否则怎么叫短信代理呢?
                    $kernel->post(q(smppproxy), q(proxysub), $subto, $body);                } elsif ( $cmd == 0x80000005 ) {                    my (undef, undef, $delstat, $delseq, $delid=                        unpack q(N4 Z*), $input;                    warn "submit nok for sms #$delseq" if $delstat;                    warn "$delseq => $delid";                } elsif ( $cmd == 0x00000001 ) {                    my (undef, undef, $bndseq, $bndname, $bndpass, $ver=                        unpack q(N2xx![N]N (Z*)2xCx3), $input;                    return if $bndname != $bndpass;                    # 没错,我们公司也是这样 root/root 的密码
                    $heap->{client}->put(                        pack q(Nxx![N]N Z*), 0x80000001, $bndseq,q(bustaxi));                    my $clid = $_[SESSION]->ID();                    $clients{$clid= "alive";                    # alive 就是说以后真有短信过来可以投递给他们了,解决了 POE::Component::TCP::Server 只能发信不能投递的问题, thanks POE maillist
                    warn "smpp client $clid started & passed test";                }            },            InlineStates    => {                scatter => sub {                    my ( $heap, $kernel, $dlvto, $dlvwhat ) =                        @_[HEAP, KERNEL, ARG0, ARG1];                    $heap->{seq} ++;                    warn "scatter get called $heap->{seq}";                    $heap->{client}->put( pack q(Nxx![N]N x(x2Z*)2Cx6CxC/A*),                                            0x00000005, $heap->{seq},                                            q(86801), $dlvto, 0, 0, $dlvwhat);                    # 发信时候请丢在这里,邮筒的名字叫做 scatter,没错就是 foxpro 里面那个 gather 的搭档
                },
            }
,
        );
        POE
::Component::Client::TCP->new (            Alias           => q(smppproxy),            Filter          => ["POE::Filter::Block", LengthCodec => [\&enc, \&dec]],            RemoteAddress   => qq(197.197.11.5),            RemotePort      => 5018,            Alias           => q(1st),            ConnectTimeout  => 100,            Connected       => sub {                my ( $kernel, $heap= @_[ KERNEL, HEAP];                ($retrytime, $seq, $bnd= ( 1, 16, 1);                warn "connected";                my  ( $bndrcv, $id, $passwd, $bndrcvlen=                    ( undef, 'bustaxi', 'bustaxi', undef, 9);                $bndrcv = pack q(Nxx![N]N (Z*)2xCx3), 0x00000001, $seq,                                                      $id, $passwd, 0x33;                $heap->{server}->put($bndrcv);                $kernel->delay(heartbeat => 20);            },            # 能够发信之前你得先有腰牌,还得有心跳
            ConnectError    => sub {                my ($kernel, $heap, $err= @_[ KERNEL, HEAP, ARG1];                $retrytime = ($retrytime > 60? 2 : ($retrytime *2);                warn "reconnecting again after $retrytime sec(s) for $err";                $kernel->delay(reconnect => $retrytime);            },            # 别总是一陈不变的定时重试,服务器没准会厌烦的
            Disconnected    => sub {                warn "reconnecting";                my ($kernel, $heap= @_[ KERNEL, HEAP];                $bnd = 0;                $kernel->yield( "reconnect" );            },            # 被踢出来是正常的,别灰心我们可以自动重连的
            ServerInput     => sub {                my ($kernel, $heap, $input= @_[ KERNEL, HEAP, ARG0];                warn "servre said";                warn HexDump $input;                # 满屏幕是你说我说他说,有了代理就热闹很多了
                my $cmd = unpack 'N', substr($input, 4, 4);                if ( $cmd == 0x00000005 ) {                    my (undef, undef, $dlvseq, $dlvfrom, $dlvto, $esm, $code, $body=                        unpack q(N2xx![N]N x(x2Z*)2Cx6CxC/A*), $input;                    $heap->{server}->put(                        pack q(N3 Z*), 0x80000005, 0, $dlvseq, q(1a2b3c4d));                    foreach my $clid (keys %clients) {                        warn "posting to $clid";                        $kernel->post($clid => scatter => $dlvfrom => $body);                    }                    # 挨家挨户骑车投递信件
                } elsif ( $cmd == 0x80000004 ) {                    my (undef, undef, $substat, $subseq, $subid=                        unpack q(N4 Z*), $input;                    warn "submit nok for sms #$subseq" if $substat;                    warn "$subseq => $subid";                # 看看挂号信的回执是不是正常
                } elsif ( $cmd == 0x80000001 ) {                    my (undef, undef, $bndstat, $bndseq=                        unpack q(N4 Z*), $input;                    warn "bind receiver nok for req #$bndseq" if $bndstat;                # 还得留神腰牌验证通过了没有
                } elsif ( $cmd == 0x80000015 ) {                    my (undef, undef, $enqstat, $enqseq=                        unpack q(N4 Z*), $input;                    warn "enqlink nok for req #$enqseq" if $enqstat;                }                # 大家都得有心跳,服务器那里给我们心跳回执,下面就是保持心跳的事件
            },
            InlineStates 
=> {                heartbeat   => sub {                    my ( $heap, $kernel ) = @_[HEAP, KERNEL];                    $heap->{server}->put( pack q(Nxx![N]N), 0x00000015, ++$seqif $bnd;                    $kernel->delay(heartbeat => 20);                },                proxysub    => sub {                    my ( $heap, $kernel, $subto, $subwhat ) =                        @_[HEAP, KERNEL, ARG0, ARG1];                    $heap->{server}->put( pack q(Nxx![N]N x(x2Z*)2Cx6CxC/A*),                                            0x00000004, ++$seq,                                            q(86800), $subto, 0, 0, $subwhat);                },                # 邮局这个辰光才真的装车
            },
        );
        POE
::Kernel->run();
    };
    
$win->btnok->Text(q(再来));    return (1);
}

 

 

 

 

google上的链接:
https://docs.google.com/Doc?docid=df26q2xp_82gr83z7&hl=en

相关文章:

  • 2021-11-06
  • 2021-11-05
  • 2021-07-18
  • 2021-11-05
  • 2021-11-05
  • 2021-11-25
  • 2022-01-17
  • 2021-04-14
猜你喜欢
  • 2021-06-10
  • 2021-05-03
  • 2021-11-06
  • 2021-06-12
  • 2021-09-25
  • 2021-07-23
  • 2021-11-05
相关资源
相似解决方案