2015年12月16日 星期三

HTML5 - websocket api 應用

WebSocket是HTML5開始提供的一種在單個 TCP 連線上進行全雙工通訊的協定。WebSocket通訊協定於2011年被IETF定為標準RFC 6455,WebSocketAPI被W3C定為標準。

在WebSocket API中,瀏覽器和伺服器只需要做一個交握的動作,然後,瀏覽器和伺服器之間就形成了一條快速通道。兩者之間就直接可以資料互相傳送。
如何進行呢?
我們提供一個範例程式來參考如下:

server.php
<?php
ob_implicit_flush();
$addrss = '127.0.0.1';
$port = 9111;
$server = socket_create(AF_INET , SOCK_STREAM , SOL_TCP);
socket_set_option($server, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($server , $addrss , $port);
socket_listen($server , 10);
$clients[] = $server;
tip("server started and listening on $port $server\n");
$blank = false;
while(true){
socket_select($clients,$write=NULL,$except=NULL,NULL);
//echo "e\n";
foreach($clients as $k => $sock){
//连接主机的client
if($sock == $server){
$client = socket_accept($server);
if($client < 0){
echo 'socket_accept() failed\n';
continue;
}else{
$clients[] = $client;
echo "connect client\n";
continue;
}
}else{
//$len = socket_recv($sock , $buffer , 2048 , 0);
$len=socket_recv($sock,$buffer,2048,0);
if($len < 7){
unset($clients[$k]);
continue;
}
if(!$blank){
$buf = substr($buffer,strpos($buffer,'Sec-WebSocket-Key:')+18);
$key = trim(substr($buf,0,strpos($buf,"\r\n")));

$new_key = base64_encode(sha1($key."258EAFA5-E914-47DA-95CA-C5AB0DC85B11",true));

$new_message = "HTTP/1.1 101 Switching Protocols\r\n";
$new_message .= "Upgrade: websocket\r\n";
$new_message .= "Sec-WebSocket-Version: 13\r\n";
$new_message .= "Connection: Upgrade\r\n";
$new_message .= "Sec-WebSocket-Accept: " . $new_key . "\r\n\r\n";
socket_write($sock,$new_message,strlen($new_message));
$blank = true;
}else{//echo 11111111111111111111111111111;die;
$str = decode($buffer);
echo "received data:$str\n";
$msg = 'hello client';
$msg = code($msg);
socket_write($sock,$msg,strlen($msg));
}

}
//$client = socket_accept($server);
//$buffer = socket_read($client, 8192);
}
}
//}
function tip($tip){
$tip = date('Y-m-d H:i:s').' : '.$tip;
echo iconv('utf-8','gbk//IGNORE',$tip);
}
function decode($buffer) {
$len = $masks = $data = $decoded = null;
$len = ord($buffer[1]) & 127;

if ($len === 126) {
$masks = substr($buffer, 4, 4);
$data = substr($buffer, 8);
} else if ($len === 127) {
$masks = substr($buffer, 10, 4);
$data = substr($buffer, 14);
} else {
$masks = substr($buffer, 2, 4);
$data = substr($buffer, 6);
}
for ($index = 0; $index < strlen($data); $index++) {
$decoded .= $data[$index] ^ $masks[$index % 4];
}
return $decoded;
}
function code($msg){
$msg = preg_replace(array('/\r$/','/\n$/','/\r\n$/',), '', $msg);
$frame = array();
$frame[0] = '81';
$len = strlen($msg);
$frame[1] = $len<16?'0'.dechex($len):dechex($len);
$frame[2] = ord_hex($msg);
$data = implode('',$frame);
return pack("H*", $data);
}
function ord_hex($data) {
$msg = '';
$l = strlen($data);
for ($i= 0; $i<$l; $i++) {
$msg .= dechex(ord($data{$i}));
}
return $msg;
}

 
另外我們再寫一支 html 做為用戶端
client.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<script src='http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js'></script>
<script>
function ini()
{
var content = 'initial';
var host = 'ws://localhost:9111/server.php';
socket = new WebSocket(host);
socket.onopen = function(){
//alert(socket.readyState);
//alert('socket has been opened');
socket.send(content);
}
socket.onmessage = function(msg){
alert(msg.data);
}

}
function sendChat(){
var content = $('textarea').val();
//alert(content);
socket.send(content);
}
</script>
</head>
<body onload='ini()'>
<textarea></textarea>
<input type='button' value='發送' onclick='sendChat($(this))'>
</body>
</html>
當我們執行 cmd 在本機中執行 server.php 時會開啟 9111 port ,當用戶端開啟 client.html 時會先跳出 hello clinet 等訊息,在網頁中輸入文字訊息回到 cmd 底下可以看到
client 丟出的訊息


1 則留言: