## 前端页面 ##
<!DOCTYPE html>
<html>
<head>
<title>chatdemo
</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1, maximum-scale=1, user-scalable=no">
<link href="https://cdn.bootcss.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet">
<style type="text/css">
html, body {
min-height: 100%; }
body {
margin: 0;
padding: 0;
width: 100%;
font-family: "Microsoft Yahei",sans-serif, Arial; }
.container {
text-align: center; }
.title {
font-size: 16px;
color: rgba(0, 0, 0, 0.3);
position: fixed;
line-height: 30px;
height: 30px;
left: 0px;
right: 0px;
background-color: white; }
.content {
background-color: #f1f1f1;
border-top-left-radius: 6px;
border-top-right-radius: 6px;
margin-top: 30px; }
.content .show-area {
text-align: left;
padding-top: 8px;
padding-bottom: 168px; }
.content .show-area .message {
width: 70%;
padding: 5px;
word-wrap: break-word;
word-break: normal; }
.content .write-area {
position: fixed;
bottom: 0px;
right: 0px;
left: 0px;
background-color: #f1f1f1;
z-index: 10;
width: 100%;
height: 160px;
border-top: 1px solid #d8d8d8; }
.content .write-area .send {
position: relative;
top: -28px;
height: 28px;
border-top-left-radius: 55px;
border-top-right-radius: 55px; }
.content .write-area #name{
position: relative;
top: -20px;
line-height: 28px;
font-size: 13px; }
</style>
</head>
<body>
<div class="container">
<div class="title">简易聊天demo
</div>
<div class="content">
<div class="show-area"></div>
<div class="write-area">
<div><button class="btn btn-default send" >发送
</button></div>
<div><input name="name" id="name" type="text" placeholder="input your name"></div>
<div>
<textarea name="message" id="message" cols="38" rows="4" placeholder="input your message..."></textarea>
</div>
</div>
</div>
</div>
<script src="http://libs.baidu.com/jquery/1.9.1/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
<script>
$(function(){
var wsurl = 'ws://127.0.0.1:9505/websocket/socket.php';
var websocket;
var i = 0;
if(window.WebSocket){
websocket = new WebSocket(wsurl);
websocket.onopen = function(evevt){
console.log("Connected to WebSocket server.");
$('.show-area').append('<p class="bg-info message"><i class="glyphicon glyphicon-info-sign"></i>Connected to WebSocket server!</p>');
}
websocket.onmessage = function(event) {
var msg = JSON.parse(event.data);
var type = msg.type;
var umsg = msg.message;
var uname = msg.name;
i++;
if(type == 'usermsg'){
$('.show-area').append('<p class="bg-success message"><i class="glyphicon glyphicon-user"></i><a name="'+i+'"></a><span class="label label-primary">'+uname+' say: </span>'+umsg+'</p>');
}
if(type == 'system'){
$('.show-area').append('<p class="bg-warning message"><a name="'+i+'"></a><i class="glyphicon glyphicon-info-sign"></i>'+umsg+'</p>');
}
$('#message').val('');
window.location.hash = '#'+i;
}
websocket.onerror = function(event){
i++;
console.log("Connected to WebSocket server error");
$('.show-area').append('<p class="bg-danger message"><a name="'+i+'"></a><i class="glyphicon glyphicon-info-sign"></i>Connect to WebSocket server error.</p>');
window.location.hash = '#'+i;
}
websocket.onclose = function(event){
i++;
console.log('websocket Connection Closed. ');
$('.show-area').append('<p class="bg-warning message"><a name="'+i+'"></a><i class="glyphicon glyphicon-info-sign"></i>websocket Connection Closed.</p>');
window.location.hash = '#'+i;
}
function send(){
var name = $('#name').val();
var message = $('#message').val();
if(!name){
alert('请输入用户名!');
return false;
}
if(!message){
alert('发送消息不能为空!');
return false;
}
var msg = {
message: message,
name: name
};
try{
websocket.send(JSON.stringify(msg));
} catch(ex) {
console.log(ex);
}
}
$(window).keydown(function(event){
if(event.keyCode == 13){
console.log('user enter');
send();
}
});
$('.send').bind('click',function(){
send();
});
}
else{
alert('该浏览器不支持web socket');
}
});
</script>
</body>
</html>
<?php
$host =
'127.0.0.1';
$port =
'9505';
$null =
NULL;
$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);
$clients =
array(
$socket);
while (
true) {
$changed =
$clients;
socket_select(
$changed,
$null,
$null,
0,
10);
if (in_array(
$socket,
$changed)) {
$socket_new = socket_accept(
$socket);
$clients[] =
$socket_new;
$header = socket_read(
$socket_new,
1024);
perform_handshaking(
$header,
$socket_new,
$host,
$port);
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]);
}
foreach (
$changed as $changed_socket) {
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;
$response_text = mask(json_encode(
array(
'type'=>
'usermsg',
'name'=>
$user_name,
'message'=>
$user_message)));
send_message(
$response_text);
break 2;
}
$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_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 < strlen(
$data); ++
$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));
}
注意事项 linux服务器要开始端口 要运行 php socket.php wx
参考文章 https://www.cnblogs.com/isdom/p/webclips028.html