08月22, 2013

HTML5 WebSockets

翻译于:http://net.tutsplus.com/tutorials/javascript-ajax/start-using-html5-websockets-today/

WebSockets是什么?

WebSockets是超越了TCP通信协议,为双向通信而生的推送(Push)技术。目前,它正在向W3C标准进行靠近,不过,最新版本的Chrome和Safari浏览器已经支持WebSockets了。

WebSocket代替了什么?

WebSockets能够代理长轮询。长轮询是一个非常有趣的概念:客户端向服务器发送请求 - 这时候,相对于之前服务器返回数据,它并没有这么做,它保持这个链接直到重新刷新,或者最新的数据准备发送 - 客户端接收到这个数据之后,从新发送一个请求。(译者注:也就是说客户端发送请求,服务端保持链接,直到超过时间或者数据返回过去,就断开链接,客户端则重新发送一个新的请求。)

这样做有它的好处:能够有效的减少延迟,一个打开的连接显然不需要花费重新打开一个新连接的时间。然而,长轮询并不是一项花哨的技术:它也有可能为一个请求而暂停,然后我们就需要一个新的连接了。

目前许多Ajax程序都是利用这个方法的 - 这可能要归结于可怜的资源利用率。(译者注:由于要保持连接,所以服务器需要耗费大量资源。)

难道就没有更好的方法直接唤醒服务器并发送数据到想要接收的客户端上而不需要诸如预留连接之类的工作吗?答案是有的,这就是推送(Push)技术。

步骤一:获取WebSocket服务器

这个教程相对于服务器方面来说将更注重于客户端的建立。

我在Windows 7上使用了XAMPP搭建了PHP服务器环境。下载phpwebsockets(一个PHP写的WebSocket服务)。(注:这个版本我遇到了一些问题,我对它进行了一些修改并将其与源文件放在一块。)有各种各样的WebSocket实现方法,如果一种不能工作,你可以尝试另外一种建立,并继续我们的教程。

开启Apache服务

步骤二:更改URL和接口

在安装过程中需要更改服务端的配置,例如在setup.class.php中:

public function __construct($host='localhost',$port=8000,$max=100)  
{  
    $this->createSocket($host,$port);  
}  

浏览文件并在适当的地方进行修改。

步骤三:开启建立客户端

让我们写一个基本的模板页面,这是我的client.php文件:

<!DOCTYPE html>  
<html>  
<head>  
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>  

    <title>WebSockets Client</title>  

</head>  
<body>  
    <div id="wrapper">  

    <div id="container">  

    <h1>WebSockets Client</h1>  

    <div id="chatLog">  

    </div><!-- #chatLog -->  
    <p id="examples">e.g. try 'hi', 'name', 'age', 'today'</p>  

    <input id="text" type="text" />  
    <button id="disconnect">Disconnect</button>  

    </div><!-- #container -->  

    </div>  
</body>  
</html>​  

步骤四:增加CSS

没什么特别的,就是键入一些标签。(原文:Nothing fancy, just space some elements out.)

body {  
font-family:Arial, Helvetica, sans-serif;  
}  
#container{  
border:5px solid grey;  
width:800px;  
margin:0 auto;  
padding:10px;  
}  
#chatLog{  
padding:5px;  
border:1px solid black;  
}  
#chatLog p {  
margin:0;  
}  
.event {  
color:#999;  
}  
.warning{  
font-weight:bold;  
color:#CCC;  
}  

步骤五:了解WebSocket事件

首先让我们尝试了解一下WebSocket事件。

事件

我们需要用到3个事件:

  • onopen:打开一个socket连接
  • onmessage:接收到一条消息
  • oncolse:关闭一个socket连接

利用这些我们可以干些什么呢?

首先我们要创建一个WebSocket对象

var socket = new WebSocket("ws://localhost:8000/socket/server/startDaemon.php");  

非常简单我们就能确定事件是否发生了:

socket.onopen = function(){  
alert("Socket has been opened!");  
}  

我们接收到短信呢?

socket.onmessage = function(msg){  
alert(msg); //Awesome!  
}  

不过,我们应该避免使用警告框,实际上应该向客户端页面融入我们所学到的东西。

步骤六:Javascript

下面让我们开始吧。首先我们需要把代码放在$(document).ready(function() {})函数里,然后我们检查用户的浏览器是否支持WebSockets。如果她们不支持,我们会向页面中append一个指向Chrome浏览器的HTML链接。

$(document).ready(function() {  
if(!("WebSocket" in window)){  
$('#chatLog, input, button, #examples').fadeOut("fast");  
$('<p>Oh no, you need a browser that supports WebSockets. How about <a href="http://www.google.com/chrome">Google Chrome</a>?</p>').appendTo('#container');  
}else{  

//The user has WebSockets  

connect();  

function connect(){  
//the connect function code is below  

}  
});  

并且你可以看到,如果用户的浏览器是支持WebSockets的话会继续执行一个我们事先定义好的connect()函数。这是代码的核心部分:我们将之前学到的开启,关闭和接收事件融入其中。

我们先定义我们服务器的URL。

var socket;  
var host = "ws://localhost:8000/socket/server/startDaemon.php";

等等,URL的话我们怎么没看到http?好吧,它是一个基于WebSocket,一个与HTTP协议不同的URL地址。这是对于我们的地址的详细解释:

理解了这个之后,让我们继续我们的connect()函数。我们将放置我们的代码在一个try/catch块内,这样如果我们的代码除了什么问题,我们可以及时的让用户知道。我们创建一个新的WebSocket连接,并通过一个message函数传递消息,这个我待会儿会详细说明。我们创建我们的onopen,onmessage以及onclose函数。注意我们也需要向用户显示当前Socket的状态,这个虽然不是必要的,但是我将它包含在内了,因为它将有助于我们调试。

  • CONNECTING = 0
  • OPEN = 1
  • CLOSED = 2

    function connect(){  
    try{  
    
    var socket;  
    var host = "ws://localhost:8000/socket/server/startDaemon.php";  
    var socket = new WebSocket(host);  
    
    message('<p class="event">Socket Status: '+socket.readyState);  
    
    socket.onopen = function(){  
     message('<p class="event">Socket Status: '+socket.readyState+' (open)');  
    }  
    
    socket.onmessage = function(msg){  
     message('<p class="message">Received: '+msg.data);  
    }  
    
    socket.onclose = function(){  
     message('<p class="event">Socket Status: '+socket.readyState+' (Closed)');  
    } 
    
    } catch(exception){  
     message('<p>Error'+exception);  
    }  
    }  
    

上面写的message函数显得相当的简单,就是将一些我们想要显示的文字追加到chatLog内向用户显示。我们在Socket事件函数中为每段标签插入适当的Class,这就是为什么在message函数中只有一个关闭段落标签。

function message(msg){  
$('#chatLog').append(msg+'</p>');  
}  

更多...

如果你一直按照操作做下来,那就已经成功了!我们已经设法创建一个基本的HTML/CSS模板,创建和建立WebSocket连接并保持用户的进程和连接。

步骤七:发送数据

相较于用一个按钮去点击发送,我比较倾向于在用户回车的时候我们监听检测,并运行send函数。13是回车键的ASCII码值。

$('#text').keypress(function(event) {  
if (event.keyCode == '13') {  
send();  
}  
});  

另外这是send()函数代码:

function send(){  

var text = $('#text').val();  
if(text==""){  
message('<p class="warning">Please enter a message');  
return ;  
}  
try{  
socket.send(text);  
message('<p class="event">Sent: '+text)  
} catch(exception){  
message('<p class="warning"> Error:' + exception);  
}  

$('#text').val("");  

}  

虽然上面的代码看起来丑爆了,但是实际上,我们在使用的时候,只需要:

socket.send(); //Thanks JavaScript  

步骤八:关闭Socket

关闭socket是非常简单的一件事:为我们的断开按钮附加一个点击事件就可以了!

$('#disconnect').click(function(){  
socket.close();  
});  

完整的JavaScript代码

$(document).ready(function() {  

  if(!("WebSocket" in window)){  
  $('#chatLog, input, button, #examples').fadeOut("fast");  
  $('<p>Oh no, you need a browser that supports WebSockets. How about <a href="http://www.google.com/chrome">Google Chrome</a>?</p>').appendTo('#container');  
  }else{  
  //The user has WebSockets  

  connect();  

  function connect(){  
  var socket;  
  var host = "ws://localhost:8000/socket/server/startDaemon.php";  

  try{  
  var socket = new WebSocket(host);  

  message('<p class="event">Socket Status: '+socket.readyState);  

  socket.onopen = function(){  
 message('<p class="event">Socket Status: '+socket.readyState+' (open)');  
  }  

  socket.onmessage = function(msg){  
 message('<p class="message">Received: '+msg.data);  
  }  

  socket.onclose = function(){  
message('<p class="event">Socket Status: '+socket.readyState+' (Closed)');  
  }   

  } catch(exception){  
 message('<p>Error'+exception);  
  }  

  function send(){  
  var text = $('#text').val();  

  if(text==""){  
  message('<p class="warning">Please enter a message');  
  return ;  
  }  
  try{  
  socket.send(text);  
  message('<p class="event">Sent: '+text)  

  } catch(exception){  
 message('<p class="warning">');  
  }  
  $('#text').val("");  
  }  

  function message(msg){  
$('#chatLog').append(msg+'</p>');  
  }  

  $('#text').keypress(function(event) {  
  if (event.keyCode == '13') {  
send();  
  }  
  }); 

  $('#disconnect').click(function(){  
 socket.close();  
  });  

  }//End connect  

  }//End else  

});  

步骤九:运行WebSocket服务

这里我们需要用命令行访问。幸运的是,XAMPP有一个很方便的shell选项。在XAMPP控制面板上点击"Shell" 并输入:

php -q path\to\server.php

现在你已经成功启动了WebSocket服务了!

结束语

当页面载入后,一个WebSocket链接将会尝试建立(尝试修改代码让用户可以自己选择连接/断开)。然后,用户能够输入消息并从服务器返回消息。

就这样了!

感谢阅读!我希望你能好好享受这篇教程!记住,尽管WebSockets非常的令人细分,但是它也有可能被抛弃。你可以关注W3C WebSocket API获取最新的消息。

本文链接:https://blog.imnerd.org/post/html5-websockets.html

-- EOF --

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。