我做的一个websocket的demo(php server),websocketdemo
notice:
通过命令行执行php文件 如 php -q c:\path\server.php
通过本地web服务器访问 http://127.0.0.1/websocket/index.php即可
notice:
需要php5.3或以上的执行环境,和一个web服务器如apache
浏览器需支持html5 web socket
这里监听 socket端口 9505,如遇到端口被占用可能需要在这两个文件内修改端口或者杀死相应端口进程
页面手机上看起来比pc上好看!
1.客户端代码 html文件
1.client code:
chatdemo
"
utf-8">
"
viewport" content=
"width=device-width,initial-scale=1, maximum-scale=1, user-scalable=no">
"
https://cdn.bootcss.com/bootstrap/3.3.2/css/bootstrap.min.css" rel=
"stylesheet">
class=
"container">
class="title">简易聊天demo
class=
"content">
class="show-area">
class=
"write-area">
"name" id="name" type="text" placeholder="input your name">
<script><span>
$(function(){
<span>var wsurl = <span>'<span>ws://127.0.0.1:9505/websocket/server.php<span>'<span>;
<span>var<span> websocket;
<span>var i = <span>0<span>;
<span>if<span>(window.WebSocket){
websocket = <span>new<span> WebSocket(wsurl);
<span>//<span>连接建立
websocket.onopen =<span> function(evevt){
console.log(<span>"<span>Connected to WebSocket server.<span>"<span>);
$(<span>'<span>.show-area<span>').append(<span>'<span><p class="bg-info message"><i class="glyphicon glyphicon-info-sign">Connected to WebSocket server!<span>'<span>);
}
<span>//<span>收到消息
websocket.onmessage = function(<span>event<span>) {
<span>var msg = JSON.parse(<span>event.data); <span>//<span>解析收到的json消息数据
<span>var type = msg.type; <span>//<span> 消息类型
<span>var umsg = msg.message; <span>//<span>消息文本
<span>var uname = msg.name; <span>//<span>发送人
i++<span>;
<span>if(type == <span>'<span>usermsg<span>'<span>){
$(<span>'<span>.show-area<span>').append(<span>'<span><p class="bg-success message"><i class="glyphicon glyphicon-user"><a name="<span>'+i+<span>'<span>"><span class="label label-primary"><span>'+uname+<span>'<span> say: <span>'+umsg+<span>'<span><span>'<span>);
}
<span>if(type == <span>'<span>system<span>'<span>){
$(<span>'<span>.show-area<span>').append(<span>'<span><p class="bg-warning message"><a name="<span>'+i+<span>'<span>"><i class="glyphicon glyphicon-info-sign"><span>'+umsg+<span>'<span><span>'<span>);
}
$(<span>'<span>#message<span>').val(<span>''<span>);
window.location.hash = <span>'<span>#<span>'+<span>i;
}
<span>//<span>发生错误
websocket.onerror = function(<span>event<span>){
i++<span>;
console.log(<span>"<span>Connected to WebSocket server error<span>"<span>);
$(<span>'<span>.show-area<span>').append(<span>'<span><p class="bg-danger message"><a name="<span>'+i+<span>'<span>"><i class="glyphicon glyphicon-info-sign">Connect to WebSocket server error.<span>'<span>);
window.location.hash = <span>'<span>#<span>'+<span>i;
}
<span>//<span>连接关闭
websocket.onclose = function(<span>event<span>){
i++<span>;
console.log(<span>'<span>websocket Connection Closed. <span>'<span>);
$(<span>'<span>.show-area<span>').append(<span>'<span><p class="bg-warning message"><a name="<span>'+i+<span>'<span>"><i class="glyphicon glyphicon-info-sign">websocket Connection Closed.<span>'<span>);
window.location.hash = <span>'<span>#<span>'+<span>i;
}
function send(){
<span>var name = $(<span>'<span>#name<span>'<span>).val();
<span>var message = $(<span>'<span>#message<span>'<span>).val();
<span>if(!<span>name){
alert(<span>'<span>请输入用户名!<span>'<span>);
<span>return <span>false<span>;
}
<span>if(!<span>message){
alert(<span>'<span>发送消息不能为空!<span>'<span>);
<span>return <span>false<span>;
}
<span>var msg =<span> {
message: message,
name: name
};
<span>try<span>{
websocket.send(JSON.stringify(msg));
} <span>catch<span>(ex) {
console.log(ex);
}
}
<span>//<span>按下enter键发送消息
$(window).keydown(function(<span>event<span>){
<span>if(<span>event.keyCode == <span>13<span>){
console.log(<span>'<span>user enter<span>'<span>);
send();
}
});
<span>//<span>点发送按钮发送消息
$(<span>'<span>.send<span>').bind(<span>'<span>click<span>'<span>,function(){
send();
});
}
<span>else<span>{
alert(<span>'<span>该浏览器不支持web socket<span>'<span>);
}
});
</script>
View Code
2.socket服务器端代码 php文件
2.php code:
php
$host =
'127.0.0.1';
$port =
'9505';
$null =
NULL;
//创建tcp socket
$socket =
socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($socket, 0, $port);
//监听端口
socket_listen($socket);
//连接的client socket 列表
$clients =
array($socket);
//设置一个死循环,用来监听连接 ,状态
while (
true) {
$changed =
$clients;
socket_select($changed, $null, $
null,
0,
10);
//如果有新的连接
if (in_array($socket, $changed)) {
//接受并加入新的socket连接
$socket_new =
socket_accept($socket);
$clients[] =
$socket_new;
//通过socket获取数据执行handshake
$header = socket_read($socket_new,
1024);
perform_handshaking($header, $socket_new, $host, $port);
//获取client ip 编码json数据,并发送通知
socket_getpeername($socket_new, $ip);
$response = mask(json_encode(array(
'type'=>
'system',
'message'=>$ip.
' connected')));
send_message($response);
$found_socket =
array_search($socket, $changed);
unset($changed[$found_socket]);
}
//轮询 每个client socket 连接
foreach ($changed
as $changed_socket) {
//如果有client数据发送过来
while(socket_recv($changed_socket, $buf,
1024,
0) >=
1)
{
//解码发送过来的数据
$received_text =
unmask($buf);
$tst_msg =
json_decode($received_text);
$user_name = $tst_msg->
name;
$user_message = $tst_msg->
message;
//把消息发送回所有连接的 client 上去
$response_text = mask(json_encode(array(
'type'=>
'usermsg',
'name'=>$user_name,
'message'=>
$user_message)));
send_message($response_text);
break 2;
}
//检查offline的client
$buf = @socket_read($changed_socket,
1024, PHP_NORMAL_READ);
if ($buf ===
false) {
$found_socket =
array_search($changed_socket, $clients);
socket_getpeername($changed_socket, $ip);
unset($clients[$found_socket]);
$response = mask(json_encode(array(
'type'=>
'system',
'message'=>$ip.
' disconnected')));
send_message($response);
}
}
}
// 关闭监听的socket
socket_close($sock);
//发送消息的方法
function send_message($msg)
{
global $clients;
foreach($clients
as $changed_socket)
{
@socket_write($changed_socket,$msg,strlen($msg));
}
return true;
}
//解码数据
function unmask($text) {
$length = ord($text[
1]) &
127;
if($length ==
126) {
$masks = substr($text,
4,
4);
$data = substr($text,
8);
}
elseif($length ==
127) {
$masks = substr($text,
10,
4);
$data = substr($text,
14);
}
else {
$masks = substr($text,
2,
4);
$data = substr($text,
6);
}
$text =
"";
for ($i =
0; $i $i) {
$text .= $data[$i] ^ $masks[$i%
4];
}
return $text;
}
//编码数据
function mask($text)
{
$b1 =
0x80 | (
0x1 &
0x0f);
$length =
strlen($text);
if($length 125
)
$header = pack(
'CC', $b1, $length);
elseif($length >
125 && $length 65536
)
$header = pack(
'CCn', $b1,
126, $length);
elseif($length >=
65536)
$header = pack(
'CCNN', $b1,
127, $length);
return $header.$text;
}
//握手的逻辑
function perform_handshaking($receved_header,$client_conn, $host, $port)
{
$headers =
array();
$lines = preg_split(
"/\r\n/", $receved_header);
foreach($lines
as $line)
{
$line =
chop($line);
if(preg_match(
'/\A(\S+): (.*)\z/', $line, $matches))
{
$headers[$matches[1]] = $matches[
2];
}
}
$secKey = $headers[
'Sec-WebSocket-Key'];
$secAccept = base64_encode(pack(
'H*', sha1($secKey .
'258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
$upgrade =
"HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
"Upgrade: websocket\r\n" .
"Connection: Upgrade\r\n" .
"WebSocket-Origin: $host\r\n" .
"WebSocket-Location: ws://$host:$port/demo/shout.php\r\n".
"Sec-WebSocket-Accept:$secAccept\r\n\r\n";
socket_write($client_conn,$upgrade,strlen($upgrade));
}
View Code
以后有空再整份java版本的