http://wm.1967it.top/
composer require webman/gateway-worker
https://www.workerman.net/doc/gateway-worker/
根据实际项目修改你当前项目的路径
头像的话自己加一张图片,这是我的路径
$("#dialog").append('<div class="speech_item"><img src="http://wm.1967it.top/public/chat/web/img/1.jpg" class="user_icon" height="42" width="50"/> '+from_client_name+' <br> '+time+'<div style="clear:both;"></div><p class="triangle-isosceles top">'+content+'</p> </div>').parseEmotion();
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>workerman-chat PHP聊天室 Websocket(HTLM5/Flash)+PHP多进程socket实时推送技术</title>
<link href="/css/bootstrap.min.css" rel="stylesheet">
<link href="/css/jquery-sinaEmotion-2.1.0.min.css" rel="stylesheet">
<link href="/css/style.css" rel="stylesheet">
<script type="text/javascript" src="/js/swfobject.js"></script>
<script type="text/javascript" src="/js/web_socket.js"></script>
<script type="text/javascript" src="/js/jquery.min.js"></script>
<script type="text/javascript" src="/js/jquery-sinaEmotion-2.1.0.min.js"></script>
<script type="text/javascript">
if (typeof console == "undefined") { this.console = { log: function (msg) { } };}
// 如果浏览器不支持websocket,会使用这个flash自动模拟websocket协议,此过程对开发者透明
WEB_SOCKET_SWF_LOCATION = "/swf/WebSocketMain.swf";
// 开启flash的websocket debug
WEB_SOCKET_DEBUG = true;
var ws, name, client_list={},room_id,client_id;
room_id = getQueryString('room_id')?getQueryString('room_id'):1;
function getQueryString(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
var r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]); return null;
}
// 连接服务端
function connect() {
// 创建websocket
ws = new WebSocket("ws://"+document.domain+":7272");
// 当socket连接打开时,输入用户名
ws.onopen = onopen;
// 当有消息时根据消息类型显示不同信息
ws.onmessage = onmessage;
ws.onclose = function() {
console.log("连接关闭,定时重连");
connect();
};
ws.onerror = function() {
console.log("出现错误");
};
}
// 连接建立时发送登录信息
function onopen()
{
if(!name)
{
show_prompt();
}
// 登录
var login_data = '{"type":"login","client_name":"'+name.replace(/"/g, '\\"')+'","room_id":'+room_id+'}';
console.log("websocket握手成功,发送登录数据:"+login_data);
ws.send(login_data);
}
// 服务端发来消息时
function onmessage(e)
{
console.log(e.data);
var data = JSON.parse(e.data);
switch(data['type']){
// 服务端ping客户端
case 'ping':
ws.send('{"type":"pong"}');
break;;
// 登录 更新用户列表
case 'login':
var client_name = data['client_name'];
if(data['client_list'])
{
client_id = data['client_id'];
client_name = '你';
client_list = data['client_list'];
}
else
{
client_list[data['client_id']] = data['client_name'];
}
say(data['client_id'], data['client_name'], client_name+' 加入了聊天室', data['time']);
flush_client_list();
console.log(data['client_name']+"登录成功");
break;
// 发言
case 'say':
//{"type":"say","from_client_id":xxx,"to_client_id":"all/client_id","content":"xxx","time":"xxx"}
say(data['from_client_id'], data['from_client_name'], data['content'], data['time']);
break;
// 用户退出 更新用户列表
case 'logout':
//{"type":"logout","client_id":xxx,"time":"xxx"}
say(data['from_client_id'], data['from_client_name'], data['from_client_name']+' 退出了', data['time']);
delete client_list[data['from_client_id']];
flush_client_list();
}
}
// 输入姓名
function show_prompt(){
name = prompt('输入你的名字:', '');
if(!name || name=='null'){
name = '游客';
}
}
// 提交对话
function onSubmit() {
var input = document.getElementById("textarea");
var to_client_id = $("#client_list option:selected").attr("value");
var to_client_name = $("#client_list option:selected").text();
ws.send('{"type":"say","to_client_id":"'+to_client_id+'","to_client_name":"'+to_client_name+'","content":"'+input.value.replace(/"/g, '\\"').replace(/\n/g,'\\n').replace(/\r/g, '\\r')+'"}');
input.value = "";
input.focus();
}
// 刷新用户列表框
function flush_client_list(){
var userlist_window = $("#userlist");
var client_list_slelect = $("#client_list");
userlist_window.empty();
client_list_slelect.empty();
userlist_window.append('<h4>在线用户</h4><ul>');
client_list_slelect.append('<option value="all" id="cli_all">所有人</option>');
for(var p in client_list){
userlist_window.append('<li id="'+p+'">'+client_list[p]+'</li>');
if (p!=client_id) {
client_list_slelect.append('<option value="'+p+'">'+client_list[p]+'</option>');
}
}
$("#client_list").val(select_client_id);
userlist_window.append('</ul>');
}
// 发言
function say(from_client_id, from_client_name, content, time){
//解析新浪微博图片
content = content.replace(/(http|https):\/\/[\w]+.sinaimg.cn[\S]+(jpg|png|gif)/gi, function(img){
return "<a target='_blank' href='"+img+"'>"+"<img src='"+img+"'>"+"</a>";}
);
//解析url
content = content.replace(/(http|https):\/\/[\S]+/gi, function(url){
if(url.indexOf(".sinaimg.cn/") < 0)
return "<a target='_blank' href='"+url+"'>"+url+"</a>";
else
return url;
}
);
$("#dialog").append('<div class="speech_item"><img src="http://lorempixel.com/38/38/?'+from_client_id+'" class="user_icon" /> '+from_client_name+' <br> '+time+'<div style="clear:both;"></div><p class="triangle-isosceles top">'+content+'</p> </div>').parseEmotion();
}
$(function(){
select_client_id = 'all';
$("#client_list").change(function(){
select_client_id = $("#client_list option:selected").attr("value");
});
$('.face').click(function(event){
$(this).sinaEmotion();
event.stopPropagation();
});
});
</script>
</head>
<body onload="connect();">
<div class="container">
<div class="row clearfix">
<div class="col-md-1 column">
</div>
<div class="col-md-6 column">
<div class="thumbnail">
<div class="caption" id="dialog"></div>
</div>
<form onsubmit="onSubmit(); return false;">
<select style="margin-bottom:8px" id="client_list">
<option value="all">所有人</option>
</select>
<textarea class="textarea thumbnail" id="textarea"></textarea>
<div class="say-btn">
<input type="button" class="btn btn-default face pull-left" value="表情" />
<input type="submit" class="btn btn-default" value="发表" />
</div>
</form>
<div>
<b>房间列表:</b>(当前在 房间<script>document.write(room_id)</script>)<br>
<a href="/?room_id=1">房间1</a> <a href="/?room_id=2">房间2</a> <a href="/?room_id=3">房间3</a> <a href="/?room_id=4">房间4</a>
<br><br>
</div>
<p class="cp">PHP多进程+Websocket(HTML5/Flash)+PHP Socket实时推送技术 Powered by <a href="http://www.workerman.net/workerman-chat" target="_blank">workerman-chat</a></p>
</div>
<div class="col-md-3 column">
<div class="thumbnail">
<div class="caption" id="userlist"></div>
</div>
<a href="http://workerman.net:8383" target="_blank"><img style="width:252px;margin-left:5px;" src="/img/workerman-todpole.png"></a>
</div>
</div>
</div>
<script type="text/javascript">var _bdhmProtocol = (("https:" == document.location.protocol) ? " https://" : " http://");document.write(unescape("%3Cscript src='" + _bdhmProtocol + "hm.baidu.com/h.js%3F7b1919221e89d2aa5711e4deb935debd' type='text/javascript'%3E%3C/script%3E"));</script>
<script type="text/javascript">
// 动态自适应屏幕
document.write('<meta name="viewport" content="width=device-width,initial-scale=1">');
$("textarea").on("keydown", function(e) {
// 按enter键自动提交
if(e.keyCode === 13 && !e.ctrlKey) {
e.preventDefault();
$('form').submit();
return false;
}
// 按ctrl+enter组合键换行
if(e.keyCode === 13 && e.ctrlKey) {
$(this).val(function(i,val){
return val + "\n";
});
}
});
</script>
</body>
</html>
/**
* 有消息时
* @param int $client_id
* @param mixed $message
*/
public static function onMessage($client_id, $message)
{
// debug
echo "client:{$_SERVER['REMOTE_ADDR']}:{$_SERVER['REMOTE_PORT']} gateway:{$_SERVER['GATEWAY_ADDR']}:{$_SERVER['GATEWAY_PORT']} client_id:$client_id session:".json_encode($_SESSION)." onMessage:".$message."\n";
// 客户端传递的是json数据
$message_data = json_decode($message, true);
if(!$message_data)
{
return ;
}
// 根据类型执行不同的业务
switch($message_data['type'])
{
// 客户端回应服务端的心跳
case 'pong':
return;
// 客户端登录 message格式: {type:login, name:xx, room_id:1} ,添加到客户端,广播给所有客户端xx进入聊天室
case 'login':
// 判断是否有房间号
if(!isset($message_data['room_id']))
{
throw new \Exception("\$message_data['room_id'] not set. client_ip:{$_SERVER['REMOTE_ADDR']} \$message:$message");
}
// 把房间号昵称放到session中
$room_id = $message_data['room_id'];
$client_name = htmlspecialchars($message_data['client_name']);
$_SESSION['room_id'] = $room_id;
$_SESSION['client_name'] = $client_name;
// 获取房间内所有用户列表
$clients_list = Gateway::getClientSessionsByGroup($room_id);
foreach($clients_list as $tmp_client_id=>$item)
{
$clients_list[$tmp_client_id] = $item['client_name'];
}
$clients_list[$client_id] = $client_name;
// 转播给当前房间的所有客户端,xx进入聊天室 message {type:login, client_id:xx, name:xx}
$new_message = array('type'=>$message_data['type'], 'client_id'=>$client_id, 'client_name'=>htmlspecialchars($client_name), 'time'=>date('Y-m-d H:i:s'));
Gateway::sendToGroup($room_id, json_encode($new_message));
Gateway::joinGroup($client_id, $room_id);
// 给当前用户发送用户列表
$new_message['client_list'] = $clients_list;
Gateway::sendToCurrentClient(json_encode($new_message));
return;
// 客户端发言 message: {type:say, to_client_id:xx, content:xx}
case 'say':
// 非法请求
if(!isset($_SESSION['room_id']))
{
throw new \Exception("\$_SESSION['room_id'] not set. client_ip:{$_SERVER['REMOTE_ADDR']}");
}
$room_id = $_SESSION['room_id'];
$client_name = $_SESSION['client_name'];
// 私聊
if($message_data['to_client_id'] != 'all')
{
$new_message = array(
'type'=>'say',
'from_client_id'=>$client_id,
'from_client_name' =>$client_name,
'to_client_id'=>$message_data['to_client_id'],
'content'=>"<b>对你说: </b>".nl2br(htmlspecialchars($message_data['content'])),
'time'=>date('Y-m-d H:i:s'),
);
Gateway::sendToClient($message_data['to_client_id'], json_encode($new_message));
$new_message['content'] = "<b>你对".htmlspecialchars($message_data['to_client_name'])."说: </b>".nl2br(htmlspecialchars($message_data['content']));
return Gateway::sendToCurrentClient(json_encode($new_message));
}
$new_message = array(
'type'=>'say',
'from_client_id'=>$client_id,
'from_client_name' =>$client_name,
'to_client_id'=>'all',
'content'=>nl2br(htmlspecialchars($message_data['content'])),
'time'=>date('Y-m-d H:i:s'),
);
return Gateway::sendToGroup($room_id ,json_encode($new_message));
}
}
/**
* 当客户端断开连接时
* @param integer $client_id 客户端id
*/
public static function onClose($client_id)
{
// debug
echo "client:{$_SERVER['REMOTE_ADDR']}:{$_SERVER['REMOTE_PORT']} gateway:{$_SERVER['GATEWAY_ADDR']}:{$_SERVER['GATEWAY_PORT']} client_id:$client_id onClose:''\n";
// 从房间的客户端列表中删除
if(isset($_SESSION['room_id']))
{
$room_id = $_SESSION['room_id'];
$new_message = array('type'=>'logout', 'from_client_id'=>$client_id, 'from_client_name'=>$_SESSION['client_name'], 'time'=>date('Y-m-d H:i:s'));
Gateway::sendToGroup($room_id, json_encode($new_message));
}
}
哈,这个嵌套好
webman爬虫项目也开源咯
https://github.com/echo-LuGuang/nothing_to_do