本文的主要内容:

  1. HTTP VS. WebSocket
  2. WebSocket 的客户端实现(JavaScript)
  3. WebSocket 的服务端实现(Java & apache WebSocketAPI)
  4. WebSocket 深入学习

HTTP VS. WebSocket

简单来讲, WebSocket 就是一种允许服务端主动向客户端 PUSH 数据的技术。

传统的 HTTP 只能是客户端先主动向服务器发起请求然后获得服务器响应。

WebSocket是HTML5开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。

在WebSocket API中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。

浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。

当你获取 Web Socket 连接后,你可以通过 send() 方法来向服务器发送数据,并通过 onmessage 事件来接收服务器返回的数据。

上面是网络上对于 websocket 的一段简短介绍。

值得一提的是,有不少人认为 websocket (于2011年被IETF定为标准RFC 6455)是一项可以取代 AJAX (约 1998 年前后得到应用)的技术。

简单的草图(。。自己画的不太极不严谨,例如说ws最开始有个 HTTP 验证漏掉了。。但是可以表达大概意思吧):

然后是我收集的一些关于 websocket 的资料:

1、WebSocket - Wikipedia 比较权威、全面

2、An Introduction to WebSockets - Treehouse Blog 生动的个人博客

3、websocket.org - Powered by Kaazing 以 websocket 为主题的网站!(websocket.org - WebSocket technology, demos, articles, and products.)

4、菜鸟教程之 websocket 赶时间的看这个。

总而言之,websocket 非常强大,应用也非常多,例如说可以用来构建基于浏览器的网页游戏、即时聊天工具之类的。

顺便收藏(主题无关 ~ ):

What's the difference between getRequestURI and getPathInfo methods in HttpServletRequest?

WebSocket 的客户端实现(JavaScript)

客户端代码完全拷贝自上面列出来的资料二

index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>WebSockets Demo</title> <link rel="stylesheet" href="style.css">
</head>
<body>
<div id="page-wrapper">
<h1>WebSockets Demo</h1> <div id="status">Connecting...</div> <ul id="messages"></ul> <form id="message-form" action="#" method="post">
<textarea id="message" placeholder="Write your message here..." required></textarea>
<button type="submit">Send Message</button>
<button type="button" id="close">Close Connection</button>
</form>
</div> <script src="app.js"></script>
</body>
</html>

/

style.css

*, *:before, *:after {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
} html {
font-family: Helvetica, Arial, sans-serif;
font-size: 100%;
background: #333;
} #page-wrapper {
width: 650px;
background: #FFF;
padding: 1em;
margin: 1em auto;
border-top: 5px solid #69c773;
box-shadow: 0 2px 10px rgba(0,0,0,0.8);
} h1 {
margin-top:;
} #status {
font-size: 0.9rem;
margin-bottom: 1rem;
} .open {
color: green;
} .closed {
color: red;
} ul {
list-style: none;
margin:;
padding:;
font-size: 0.95rem;
} ul li {
padding: 0.5rem 0.75rem;
border-bottom: 1px solid #EEE;
} ul li:first-child {
border-top: 1px solid #EEE;
} ul li span {
display: inline-block;
width: 90px;
font-weight: bold;
color: #999;
font-size: 0.7rem;
text-transform: uppercase;
letter-spacing: 1px;
} .sent {
background-color: #F7F7F7;
} .received {} #message-form {
margin-top: 1.5rem;
} textarea {
width: 100%;
padding: 0.5rem;
font-size: 1rem;
border: 1px solid #D9D9D9;
border-radius: 3px;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1);
min-height: 100px;
margin-bottom: 1rem;
} button {
display: inline-block;
border-radius: 3px;
border: none;
font-size: 0.9rem;
padding: 0.6rem 1em;
color: white;
margin: 0 0.25rem;
text-align: center;
background: #BABABA;
border-bottom: 1px solid #999;
} button[type="submit"] {
background: #86b32d;
border-bottom: 1px solid #5d7d1f;
} button:hover {
opacity: 0.75;
cursor: pointer;
}

/

app.js

window.onload = function() {

    // Get references to elements on the page.
var form = document.getElementById('message-form');
var messageField = document.getElementById('message');
var messagesList = document.getElementById('messages');
var socketStatus = document.getElementById('status');
var closeBtn = document.getElementById('close'); // The rest of the code in this tutorial will go here...
// Create a new WebSocket.
var socket = new WebSocket('ws://echo.websocket.org'); // Show a connected message when the WebSocket is opened.
socket.onopen = function(event) {
socketStatus.innerHTML = 'Connected to: ' + event.currentTarget.url;
socketStatus.className = 'open';
}; // Handle any errors that occur.
socket.onerror = function(error) {
console.log('WebSocket Error: ' + error);
}; // Send a message when the form is submitted.
form.onsubmit = function(e) {
e.preventDefault(); // Retrieve the message from the textarea.
var message = messageField.value; // Send the message through the WebSocket.
socket.send(message); // Add the message to the messages list.
messagesList.innerHTML += '<li class="sent"><span>Sent:</span>' + message +
'</li>'; // Clear out the message field.
messageField.value = ''; return false;
}; // Handle messages sent by the server.
socket.onmessage = function(event) {
var message = event.data;
messagesList.innerHTML += '<li class="received"><span>Received:</span>' +
message + '</li>';
}; // Show a disconnected message when the WebSocket is closed.
socket.onclose = function(event) {
socketStatus.innerHTML = 'Disconnected from WebSocket.';
socketStatus.className = 'closed';
}; // Close the WebSocket connection when the close button is clicked.
closeBtn.onclick = function(e) {
e.preventDefault(); // Close the WebSocket.
socket.close(); return false;
};
};

/

直接把 三个文件放在同一个目录下,用浏览器打开 index.html 就可以用了。连接的是代码原作者的 websocket 服务器。

WebSocket 的服务端实现(Java & apache WebSocketAPI)

构建WebSocket 服务器的方式有很多,不过我只会用 tomcat 的 API,代码即是Tomcat 的 websocket example 相比自己写的肯定要规范些。↓

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sample.web; import java.io.IOException;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger; import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint; @ServerEndpoint(value = "/websocket")
public class ChatAnnotation { private static final String GUEST_PREFIX = "Guest";
private static final AtomicInteger connectionIds = new AtomicInteger();
private static final Set<ChatAnnotation> connections =
new CopyOnWriteArraySet<>(); private final String nickname;
private Session session; public ChatAnnotation() {
nickname = GUEST_PREFIX + connectionIds.getAndIncrement();
} @OnOpen
public void start(Session session) {
this.session = session;
connections.add(this);
String message = String.format("* %s %s", nickname, "has joined.");
broadcast(message);
} @OnClose
public void end() {
connections.remove(this);
String message = String.format("* %s %s",
nickname, "has disconnected.");
broadcast(message);
} @OnMessage
public void incoming(String message) {
// Never trust the client
String filteredMessage = String.format("%s: %s",
nickname, message.toString());
broadcast(filteredMessage);
} @OnError
public void onError(Throwable t) throws Throwable {
} private static void broadcast(String msg) {
for (ChatAnnotation client : connections) {
try {
synchronized (client) {
client.session.getBasicRemote().sendText(msg);
}
} catch (IOException e) {
connections.remove(client);
try {
client.session.close();
} catch (IOException e1) {
// Ignore
}
String message = String.format("* %s %s",
client.nickname, "has been disconnected.");
broadcast(message);
}
}
}
}

在运行之前需要修改 app.js 中的地址:

    // The rest of the code in this tutorial will go here...
// Create a new WebSocket.
var socket = new WebSocket('ws://localhost:8080/websocket');

WebSocket 深入学习

当然,上面仅用到了 WebSocket API 的一个小子集,要想真正用好这些 API 并没那么简单。下面是我找到的一些学习资料(基本上看 URL 就知道什么内容了):

1、https://docs.oracle.com/javaee/7/api/javax/websocket/package-summary.html

2、https://docs.oracle.com/javaee/7/tutorial/websocket.htm

3、http://www.oracle.com/technetwork/articles/java/jsr356-1937161.html

4、https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java

5、http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/HomeWebsocket/WebsocketHome.html

6、http://www.baeldung.com/java-websockets

7、https://tomcat.apache.org/tomcat-9.0-doc/websocketapi/index.html

8、https://benas.github.io/2016/02/21/using-the-java-api-for-webSocket-to-create-a-chat-server.html

Web开发相关笔记 #04# WebSocket的更多相关文章

  1. Web开发相关笔记 #03#

    HTTP Status 500  ※  jsp 放在 WEB-INF 外面  ※ 使用 JDBC 时需要 close 什么 ※ execute 和 executeUpdate ※ How can I ...

  2. Web开发相关笔记 #01#

    前端学习纲要 ※jQuery 参考 ※ 整理 Chrome 收藏夹的小技巧 ※ 解决 AJAX 跨域获取 cookie ※ 记一次 MyBatis 相关的 debug [1] 前端学习纲要: ♦ 第一 ...

  3. Web开发相关笔记 #05# MySQL中文无法匹配

    2018-06-02 在 Class.forName 的时候记得先尝试 import 一下. 2018-06-04 1.JDBC SELECT 查询,中文条件查不出东西,可能是字符编码问题: Stri ...

  4. Web开发相关笔记 #02#

    [1] HTML 插入第三方. [2] [3] JavaScript 回调函数 & 模块化 --> 用变量封装数据.方法 --> 类比 Java 中的 package var fe ...

  5. Web开发相关笔记

    1.MySQL命令行下执行.sql脚本详解http://database.51cto.com/art/201107/277687.htm 在可视化工具里导出.sql脚本 --> 放命令行里运行 ...

  6. 【前端】移动端Web开发学习笔记【2】 & flex布局

    上一篇:移动端Web开发学习笔记[1] meta标签 width设置的是layout viewport 的宽度 initial-scale=1.0 自带 width=device-width 最佳实践 ...

  7. 【前端】移动端Web开发学习笔记【1】

    下一篇:移动端Web开发学习笔记[2] Part 1: 两篇重要的博客 有两篇翻译过来的博客值得一看: 两个viewport的故事(第一部分) 两个viewport的故事(第二部分) 这两篇博客探讨了 ...

  8. ASP.NET Core Web开发学习笔记-1介绍篇

    ASP.NET Core Web开发学习笔记-1介绍篇 给大家说声报歉,从2012年个人情感破裂的那一天,本人的51CTO,CnBlogs,Csdn,QQ,Weboo就再也没有更新过.踏实的生活(曾辞 ...

  9. Django Web开发指南笔记

    Django Web开发指南笔记 语句VS表达式 python代码由表达式和语句组成,由解释器负责执行. 主要区别:表达式是一个值,它的结果一定是一个python对象:如:12,1+2,int('12 ...

随机推荐

  1. Scala对class/object反射

    近期有需求,要根据解析字符串,根据字符串的内容去调用方法.想到的基本就是使用反射.但是基本上能找到的资料,全没有讲scala的反射.只有零星点点的讲解.大部分都是用scala的语法写java反射最后翻 ...

  2. Python 正在表达式

    什么是正则表达式 正则表达式:是一组特殊的字符序列,又称为规则表达式,它能方便你检查一个字符串是否与某种模式匹配.通常用来检索和替换那些符合某些模式的文本.python中的re模块,实现了全部的正则表 ...

  3. zabbix 配合钉钉群机器人(webhook) 报警

    首先建钉钉群,添加一个自定义机器人拿到webhook zabbix添加一个报警媒介 搞一个shell脚本来启动Python脚本(直接用zabbix调Python脚本不行,不知道什么原因) vim di ...

  4. char varchar

    对于字符类型的有:char:固定长度,存储ANSI字符,不足的补英文半角空格.nchar:固定长度,存储Unicode字符,不足的补英文半角空格varchar:可变长度,存储ANSI字符,根据数据长度 ...

  5. git issue 汇总

    (1)部分: https://wiki.mahara.org/wiki/Developer_Area/Contributing_Code/Troubleshooting_your_Gerrit_con ...

  6. 编译snort经验

    google搜索,找个感觉挺新的版本 https://zh.osdn.net/frs/g_redir.php?m=netix&f=%2Fslackbuildsdirectlinks%2Fsno ...

  7. js中两个!!的理解

    在js中经常有两个!!出现,经常让人难以理解 (function () { var a = 10; var b = 20; function add(num1, num2) { var num1 = ...

  8. cocos2d-x C++ (Android)集成第三方微信分享

    ShareSDK Android for cocos2d-x 此文档为ShareSDK Android for cocos3.x的版本,如您集成的是2.X的版本文档请到这里:cocos2.x集成文档 ...

  9. RESTful 和RPC

    RESTful 全称是 Resource Representational State Transfer 即资源表现状态转换 通俗来说就是 资源在网络中以某种表现形式进行状态转移 RPC 全称是Rem ...

  10. VS 星期作业 if else的应用 做一个受不受异性欢迎的小程序

    static void Main(string[] args) { //漏掉代码 输入错误 进行提示! string T1, T2, T3, T4, T5, T6, T7, T8, T9, T10=& ...