客户端:

<!DOCTYPE html>
<html>
<head>
<title></title>
<style>
#win{ border:1px solid #ccc; padding:20px ; color:#333; line-height:2em; }
.input{ padding:10px 0px; text-align:left;}
.input input{ width:200px;}
</style>
</head>
<body>
<div id=”win”></div>
<div><input id=”text”><button id=”send”>发送</button><button id=”disconnect”>断开连接</button></div>
<script>
function log(d){
var logDiv=document.createElement(“div”);
logDiv.innerHTML=d;
document.getElementById(“win”).appendChild(logDiv);
}
//创建websocket连接
var socket=new WebSocket(“ws://localhost:12345/websocket/server.php”);
//绑定连接成功事件
socket.onopen=function(){
log(“Socket ReadyState:”+socket.readyState);
//socket.send(“hi”);
};
//绑定接收到信息事件
socket.onmessage=function(e){
log(e.data);
}
//绑定关闭连接事件
socket.onclose=function(){
log(“close!”);
log(“Socket ReadyState:”+socket.readyState);
}
//发送信息至服务器
function send(){
var texts=document.getElementById(“text”).value;
socket.send(texts);
document.getElementById(“text”).value=”";
}
//绑定其他DOM事件
document.getElementById(“send”).onclick=send;
document.getElementById(“text”).onkeyup=function(e){
if(e.keyCode==13) send();
}
document.getElementById(“disconnect”).onclick=function(){
socket.close();
}
</script>
</body>
</html>

服务器端server.php

<?php

/*  >php -q server.php  */

error_reporting(E_ALL);

set_time_limit(0);

ob_implicit_flush();

$master  = WebSocket(“localhost”,12345);

$sockets = array($master);

$users   = array();

$debug   = true;

while(true){

$changed = $sockets;

socket_select($changed,$write=NULL,$except=NULL,NULL);

foreach($changed as $socket){

if($socket==$master){

$client=socket_accept($master);

if($client<0){ console(“socket_accept() failed”); continue; }

else{ connect($client); }

}

else{

$bytes = @socket_recv($socket,$buffer,2048,0);

if($bytes==0){ disconnect($socket); }

else{

$user = getuserbysocket($socket);

if(!$user->handshake){ dohandshake($user,$buffer); }

else{ process($user,$buffer); }

}

}

}

}

//—————————————————————

function process($user,$msg){

global $sockets,$users;

$action = unwrap($msg);

say(“< “.$action);

if(!$user->init){

$user->user=$action;

send($user->socket,”hello “.$user->user);

send($user->socket,”You can Chat Now!”);

$user->init=true;

return;

}

foreach($users as $otherUser){

send($otherUser->socket,$user->user.”:”.$action);

}

/*

switch($action){

case “hello” : send($user->socket,”hello human”);                       break;

case “hi”    : send($user->socket,”zup human”);                         break;

case “name”  : send($user->socket,”my name is Multivac, silly I know”); break;

case “age”   : send($user->socket,”I am older than time itself”);       break;

case “date”  : send($user->socket,”today is “.date(“Y.m.d”));           break;

case “time”  : send($user->socket,”server time is “.date(“H:i:s”));     break;

case “thanks”: send($user->socket,”you’re welcome”);                    break;

case “bye”   : send($user->socket,”bye”);                               break;

default      : send($user->socket,$action.” not understood”);           break;

}

*/

}

function send($client,$msg){

say(“> “.$msg);

$msg = wrap($msg);

socket_write($client,$msg,strlen($msg));

}

function WebSocket($address,$port){

$master=socket_create(AF_INET, SOCK_STREAM, SOL_TCP)     or die(“socket_create() failed”);

socket_set_option($master, SOL_SOCKET, SO_REUSEADDR, 1)  or die(“socket_option() failed”);

socket_bind($master, $address, $port)                    or die(“socket_bind() failed”);

socket_listen($master,20)                                or die(“socket_listen() failed”);

echo “Server Started : “.date(‘Y-m-d H:i:s’).”\n”;

echo “Master socket  : “.$master.”\n”;

echo “Listening on   : “.$address.” port “.$port.”\n\n”;

return $master;

}

function connect($socket){

global $sockets,$users;

$user = new User();

$user->id = uniqid();

$user->socket = $socket;

array_push($users,$user);

array_push($sockets,$socket);

console($socket.” CONNECTED!”);

}

function disconnect($socket){

global $sockets,$users;

$found=null;

$n=count($users);

for($i=0;$i<$n;$i++){

if($users[$i]->socket==$socket){ $found=$i; break; }

}

if(!is_null($found)){ array_splice($users,$found,1); }

$index = array_search($socket,$sockets);

//socket_close($socket);

console($socket.” DISCONNECTED!”);

if($index>=0){ array_splice($sockets,$index,1); }

}

function dohandshake($user,$buffer){

console(“\nRequesting handshake…”);

console($buffer);

list($resource,$host,$origin,$strkey1,$strkey2,$data) = getheaders($buffer);

console(“Handshaking…”);

$pattern = ‘/[^\d]*/’;

$replacement = ”;

$numkey1 = preg_replace($pattern, $replacement, $strkey1);

$numkey2 = preg_replace($pattern, $replacement, $strkey2);

$pattern = ‘/[^ ]*/’;

$replacement = ”;

$spaces1 = strlen(preg_replace($pattern, $replacement, $strkey1));

$spaces2 = strlen(preg_replace($pattern, $replacement, $strkey2));

/*

if ($spaces1 == 0 || $spaces2 == 0 || $numkey1 % $spaces1 != 0 || $numkey2 % $spaces2 != 0) {

//socket_close($user->socket);

console(‘failed’);

return false;

}

*/

$ctx = hash_init(‘md5′);

hash_update($ctx, pack(“N”, $numkey1/$spaces1));

hash_update($ctx, pack(“N”, $numkey2/$spaces2));

hash_update($ctx, $data);

$hash_data = hash_final($ctx,true);

$upgrade  = “HTTP/1.1 101 WebSocket Protocol Handshake\r\n” .

“Upgrade: WebSocket\r\n” .

“Connection: Upgrade\r\n” .

“Sec-WebSocket-Origin: ” . $origin . “\r\n” .

“Sec-WebSocket-Location: ws://” . $host . $resource . “\r\n” .

“\r\n” .

$hash_data;

socket_write($user->socket,$upgrade.chr(0),strlen($upgrade.chr(0)));

$user->handshake=true;

console($upgrade);

console(“Done handshaking…”);

sendHello($user);

return true;

}

function sendHello($user){

send($user->socket,”hello!”);

send($user->socket,”Welcome to ChatRoom”);

send($user->socket,”Please Enter Your NickName!”);

$user->init=false;

}

function getheaders($req){

$r=$h=$o=null;

if(preg_match(“/GET (.*) HTTP/”   ,$req,$match)){ $r=$match[1]; }

if(preg_match(“/Host: (.*)\r\n/”  ,$req,$match)){ $h=$match[1]; }

if(preg_match(“/Origin: (.*)\r\n/”,$req,$match)){ $o=$match[1]; }

if(preg_match(“/Sec-WebSocket-Key2: (.*)\r\n/”,$req,$match)){ $key2=$match[1]; }

if(preg_match(“/Sec-WebSocket-Key1: (.*)\r\n/”,$req,$match)){ $key1=$match[1]; }

if(preg_match(“/\r\n(.*?)\$/”,$req,$match)){ $data=$match[1]; }

return array($r,$h,$o,$key1,$key2,$data);

}

function getuserbysocket($socket){

global $users;

$found=null;

foreach($users as $user){

if($user->socket==$socket){ $found=$user; break; }

}

return $found;

}

function     say($msg=”"){ echo $msg.”\n”; }

function    wrap($msg=”"){ return chr(0).$msg.chr(255); }

function  unwrap($msg=”"){ return substr($msg,1,strlen($msg)-2); }

function console($msg=”"){ global $debug; if($debug){ echo $msg.”\n”; } }

class User{

var $id;

var $socket;

var $handshake;

var $user;

var $init;

}

?>