websocket 前端+php

xiaoxiao2021-03-01  21

## 前端页面 ## <!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); //解析收到的json消息数据 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); } } //按下enter键发送消息 $(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> ## socket.php ## <?php $host = '127.0.0.1'; $port = '9505'; //linux要开启端口 $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 < 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

转载请注明原文地址: https://www.6miu.com/read-4050018.html

最新回复(0)