websocket draft-15 服务端握手Demo的perl实现

websocket这个坑爹的项目一直都在草案中,而且有时的更新变化还挺大的。目前最新的版本要先握手,信任后再发送相应数据,数据还掩码了。这次先实现了握手功能,其原理如下:

1.客端向服务器端发送类似这样的HTTP头:

 

        GET / HTTP/1.1
        Upgrade: websocket
        Connection: Upgrade
        Host: localhost:8000
        Sec-WebSocket-Origin: null
        Sec-WebSocket-Key: FcJ21uh+iiDs7haoaG1cKQ==
        Sec-WebSocket-Version: 8

 

 

其中

    Upgrade:wesocket 描述了该信息是websocket协议,

    Host:localhost:8000 这个就是请求的主机地址和端口号,

    Sec-WebSocket-Version:8 是版本号,这里是8,用的chrome14作的测试

    Sec-WebSocket-Key: FcJ21uh+iiDs7haoaG1cKQ== 这条是很重要的,FcJ21uh+iiDs7haoaG1cKQ==是客户端提供的握手所用的key,需要服务器端根据该key作相应计算后返回一个对应的key来完成握手,具体的计算方法马上就会说到。

 

2. 服务器端

        服务器端接收到请求的数据后,先根据头来判断是否为websocket协议,是的话就会先作握手处理,然后再进行数据的相互发送,这里先只讨论握手,数据发送的内容下次再说了。。。。

            握手步骤:

      (1)服务器端获取到客户端发送过来的 Sec-WebSocket-Key 值(比如这里的 FcJ21uh+iiDs7haoaG1cKQ== );

      (2)将获取到的key值与一个magic string “258EAFA5-E914-47DA-95CA-C5AB0DC85B11” 连接成一个新的key串 "FcJ21uh+iiDs7haoaG1cKQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11",这个magic string为标准里给出的值,可以看作为一个唯一ID序列;

      (3)将新生成的串进行SHA1编码,生成一个由多组两位16进制数构成的加密串,比如这里的 "FcJ21uh+iiDs7haoaG1cKQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11" 将生成 "11a8a543955aaf7f9a266c55b2a9cda3151cdec5";

      (4)把加密串按2位16进制数字分隔,进行base64编码生成最终的key:base64编码(11 a8 a5 43 95 5a af 7f 9a 26 6c 55 b2 a9 cd a3 15 1c de c5);

      (5)将最终生成的key以Sec-WebSocket-Accept:key值 整合到返回头中返回给客户端(该例子的key计算结果为 EailQ5Var3+aJmxVsqnNoxUc3sU=):

 

            HTTP/1.1 101 Web Socket Protocol Handshake
            Upgrade: websocket
            Connection: Upgrade
            Sec-WebSocket-Accept: EailQ5Var3+aJmxVsqnNoxUc3sU=
            WebSocket-Origin: localhost
            WebSocket-Location: ws://localhost:8000

 

服务端应答后就完成了这一次的握手,完整代码如下:

 

# !perl -w
use strict;

use IO::Handle;
use  Socket;
use Digest::SHA1 qw(sha1 sha1_hex sha1_base64);
use MIME::Base64;

my  $buff;
my  $port= 8000;
my  $host= ' localhost ';
my  $packhost=inet_aton( $host);
my  $address=sockaddr_in( $port, $packhost);
my  $msg= "";
my  $magicString= " 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 ";
my  $serverKey= "";

sub getClientKey{
     my  $ret= "";
     if( $_[ 0]=~m " Sec-WebSocket-Key: ([^\s]*) "s){
         $ret=$ 1;
    } else{
         # print "no matched";
    }
    
     $ret=~s/\s//g;
     return  $ret;
}

sub formatSHA1Hex{
     my  $ret= "";
     my  $len= length( $_[ 0]);
     my  $i;

     for( $i= 0; $i< $len; $i+= 2){
         $ret.= chr( oct( " 0x ". substr( $_[ 0], $i, 2)));
    }

     return  $ret;
}

socket(SERVER,AF_INET,SOCK_STREAM, getprotobyname( ' tcp '));
bind(SERVER, $address);
listen(SERVER, 10);

while( 1){
     accept(CLIENT,SERVER);
     sysread(CLIENT, $buff, 1000);
     $serverKey=encode_base64(formatSHA1Hex(sha1_hex(getClientKey( $buff). $magicString)));
     print  " $buff\n ";

     $msg= " HTTP/1.1 101 Web Socket Protocol Handshake\r\n ".
             " Upgrade: websocket\r\n ".
             " Connection: Upgrade\r\n ".
             " Sec-WebSocket-Accept:  ". $serverKey. " \r\n ".
             " WebSocket-Origin: $host\r\n ".
             " WebSocket-Location: ws://$host:$port\r\n\r\n ";

    CLIENT->autoflush( 1);
     syswrite(CLIENT, $msg);
     close CLIENT;
}
close SERVER;
exit  1;

 

为了让代码尽量简单,省去了websockt协议验证之类的细节部分,只列出了核心功能。而且此次只实现了握手部分,而且比较简单,数据相互通信的部分看哪天又闲得蛋疼的时候再写了。。。

 

转载于:https://www.cnblogs.com/Random/archive/2011/09/28/2194812.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值