不会的要多查多问,不然不会的永远不会,哪怕你离会就差了那么一点点
Websocket通信实例,配合后端php
[ 2016/09/27 21:14 | by 刘新修 ]
本站测试实例访问地址: http://code.liuxinxiu.com/php/Interface/html/WebSocket.html
XML/HTML代码
- <!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="http://code.liuxinxiu.com/lib/bootstrap/3.3.2/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;
- z-index:1000;
- 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://code.liuxinxiu.com/lib/jquery/1.9.1/jquery.min.js"></script>
- <script src="http://code.liuxinxiu.com/lib/bootstrap/3.3.2/bootstrap.min.js"></script>
- <script>
- $(function(){
- var wsurl='ws://code.liuxinxiu.com:9090/php/webSocket/server.php';
- var websocket;
- var i = 0;
- /******** 判断是否有webSocket对象 *******/
- if(window.WebSocket){
- websocket=new WebSocket(wsurl);
- /******** 连接建立||发起webSocket连接 ********/
- websocket.onopen = function(evevt){
- console.log("Connected to WebSocket server.");
- /******** 监听ready状态码 ********/
- console.log('websocket.readyState:'+websocket.readyState);
- /*********************************************************
- 值为0值表示该连接尚未建立
- 值为1表示连接建立和沟通是可能的
- 值为2表示连接是通过将结束握手
- 值为3表示连接已关闭或无法打开
- *********************************************************/
- /******** 判断状态码为1则连接成功即可正常通信********/
- if(websocket.readyState==1){
- $('.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消息数据
- console.log("\n--->>message:\n"+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);
- }
- }
- //按下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>
后端PHP代码部分:
PHP代码
- 2.php code:
- <?php
- $host = '127.0.0.1';
- $port = '9090';
- $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));
- }