设为首页 收藏本站
查看: 1259|回复: 0

[经验分享] Perl实现Websocket-76的TCP并发连接服务器端

[复制链接]

尚未签到

发表于 2017-5-19 13:16:51 | 显示全部楼层 |阅读模式
  直接上代码:
  


################################################################################
# Filename:
#   websocket.pl
# Description:
#   Perl mutithreaded TCP server of HTML5 Websocket-draft-76
# Test enviroment:
#   OS      - Windows XP
#   Perl    - ActivePerl 5.12.1
#   Browser - Chrome 8.0
################################################################################
#!/usr/bin/perl -w
use strict;
use warnings;
use 5.010;
use IO::Socket::INET;
use Digest::MD5 qw/md5/;
use Redis;
use POSIX ':sys_wait_h';
### main part ##################################################################
### system level options
my %VARS = (
DEBUG => 1,
LOG2FILE => 0
);
#common global variables
my @TIMER_TASK;   #its element is %{task_name, interval fun_ref}
### stdout to log file
if( $VARS{LOG2FILE} ){
open LOG, ">>syslog.txt";
select LOG;
}
### redis db initialization
my $r = Redis->new;
$r->ping or die now() . "[Server]: connect Redis failed";
$r->flushall;
my $redis_sock = $$r{sock};
$r->hset("sys:sock", "redis", $redis_sock);
say now() . " | Redis: " . $redis_sock->sockhost() . ":" . $redis_sock->sockport() .
" <---> " . $redis_sock->peerhost() . ":" . $redis_sock->peerport();
### tcp server
my $PORT = 8000;
my $server = IO::Socket::INET->new( Proto     => 'tcp',
LocalPort => $PORT,
Listen    => 255,
Reuse     => 1);
$server or die now() . "[Server]: Err = can't setup server";
say now() . " | Server: Listening at TCP:" . $server->sockport;
#zombie
my $zombies = 0;
$SIG{CHLD} = sub {$zombies++;};
while(my $client = $server->accept()){
#zombie reaper
while($zombies) {
$zombies = 0;
while ((my $zombie = waitpid( -1, WNOHANG)) != -1){}
};
$client->autoflush(1);
#handshake
sysread $client, my $handshake_req, 1024;
my($handshake_resp,$page) = handshake($handshake_req);
print $client $handshake_resp;
close $client unless $client;
my $client_info = $client->peerhost() . ":" . $client->peerport() . "$page";
$r->hset("sys:sock", $client_info,$client);
say now() . " | Client: connected from " . $client_info;
#data framing
$client->blocking(0);
#fork child for new connection
if(my $child = fork()){     
$/ = "\xff";  #new line seperator
my($req,@resp);
while(<$client>){   
/\x00(.*)\xff/;
$req = $1;   
say now() . " | ws://" . "$client_info >>> [$req]" if $VARS{DEBUG};

@resp = request($req);
foreach my $resp (@resp){
say now() . " | ws://" . "$client_info <<< [$resp]" if $VARS{DEBUG};
print $client "\x00$resp\xff";
}   
}
return;    #go back to parent
}
}
### sub routines ###############################################################
# Description:  Request format from webSocket
# Format:       command param1,param2, ... ,paramN
sub request{
my @resp = ();
$_ = shift;  
my($cmd, @param) = split / /;
$cmd = "req_$cmd";
if(defined(&$cmd)){
no strict 'refs';
@resp = $cmd->(@param);
}else{
push @resp, "!$_";
}
return @resp;
}
sub req_echo{ return @_; }
sub req_random{
$_ = shift;
my $r;
if(/float/){ #float
$r = rand(100);
}else{    #integer
$_ = "int";
$r = int(rand(100));
}
return ("random: $_ = $r");
}
sub req_showsock{
my @socks = ();
my %s = $r->hgetall("sys:sock");
say "..............";
foreach (keys %s){
say ;
#push @socks, $item;
}
return @socks;
}

sub now{
my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
$year += 1900;
return sprintf("%.4d-%.2d-%.2d %2d:%.2d:%.2d",$year,$mon,$mday,$hour,$min,$sec);
}
sub handshake{
my $req = shift;
($req, my $key3) = split /\r\n\r\n/, $req;  
my @req = split /\r\n/, $req;
my $field = shift @req;
$field =~ /GET (.*) HTTP/;
my $page = $1;
$field = shift @req;
$field = shift @req;
$field = shift @req;
$field =~ /Host: (.*)/;
my $location = "ws://" . $1 . $page;
$field = shift @req;
$field =~ /Origin: (.*)/;
my $origin = $1;
$field = shift @req;
$field =~ /Sec-WebSocket-Key1: (.*)/;
$field = $1;
my @key1= $field =~ /([0-9])/g;
my $key1 = join('', @key1) + 0;
my @space1 = $field =~ /\x20/g;
my $space1 = @space1 + 0;
my $part1 = $key1 / $space1;
my $part1_hex = pack 'L>', $part1;
$field = shift @req;
$field =~ /Sec-WebSocket-Key2: (.*)/;
$field = $1;
my @key2 = $field =~ /([0-9])/g;
my $key2 = join('', @key2) + 0;
my @space2 = $field =~ /\x20/g;
my $space2 = @space2 + 0;
my $part2 = $key2 / $space2;
my $part2_hex = pack 'L>', $part2;
my $challenge = md5($part1_hex, $part2_hex, $key3);
my $resp = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
"Upgrade: WebSocket\r\n" .
"Connection: Upgrade\r\n" .
"Sec-WebSocket-Origin: $origin\r\n" .
"Sec-WebSocket-Location: $location\r\n\r\n" . $challenge;  
return ($resp, $page);
}
sub hexcode{
my $str = unpack 'H*', shift;
$str =~ s/(.)(.)/\U$1$2 /g;
return $str;
}

 

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-379134-1-1.html 上篇帖子: 随手记一记学Perl 时容易搞混的地方 下篇帖子: [经验总结]Perl读取Excel数据并调用MSXML接口操作XML数据
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表