websocket学习和使用
1)WebSocket介绍
HTML5 Web Sockets规范定义了Web Sockets API,支持页面使用Web Socket协议与远程主机进行全双工的通信。它引入了WebSocket接口并且定义了一个全双工的通信通道,通过一个单一的套接字在Web上进行操作。HTML5 Web Sockets以最小的开销高效地提供了Web连接。相较于经常需要使用推送实时数据到客户端甚至通过维护两个HTTP连接来模拟全双工连接的旧的轮询或长轮询(Comet)来说,这就极大的减少了不必要的网络流量与延迟。
要使用HTML5 Web Sockets从一个Web客户端连接到一个远程端点,你要创建一个新的WebSocket实例并为之提供一个URL来表示你想要连接到的远程端点。该规范定义了ws://以及wss://模式来分别表示WebSocket和安全WebSocket连接。一个WebSocket连接是在客户端与服务器之间HTTP协议的初始握手阶段将其升级到Web Socket协议来建立的,其底层仍是TCP/IP连接。
2)优点
a)、服务器与客户端之间交换的标头信息很小,大概只有2字节;
b)、客户端与服务器都可以主动传送数据给对方;
c)、不用频率创建TCP请求及销毁请求,减少网络带宽资源的占用,同时也节省服务器资源;
3)WebSocket数据帧的介绍
a)、草案版本00到草案版本05之间,详细可以查看草案文档,解码编码可以看见Netty的WebSocketFrameDecoder和WebSocketFrameEncoder实现;
b)、草案版本06到现在最新的草案17,介绍参见文章:http://blog.csdn.net/fenglibing/article/details/6852497
4)WebSocket不同版本的几种握手方式
a)、无安全key、最老的WebSocket握手协议的实现(Flash);
b)、带两个安全key请求头的后端握手实现;
c)、带一个安全key请求头的后端握手实现;
参见:http://blog.csdn.net/fenglibing/article/details/7100070
5)WebSocket可以穿越防火墙吗?
WebSocket使用标准的80及443端口,这两个都是防火墙友好协议,Web Sockets使用HTTP Upgrade机制升级到Web Socket协议。HTML5 Web Sockets有着兼容HTTP的握手机制,因此HTTP服务器可以与WebSocket服务器共享默认的HTTP与HTTPS端(80和443)。
6)、Web Sockets与代理服务器交互
代理服务器的问题:
a)、HTTP代理服务器可能会选择关闭流或闲置的WebSocket连接,因为它们看起好像是尝试连接一个没有回应的HTTP服务器;
b)、代理服务器可能会缓冲未加密的HTTP响应,这将会对HTTP响应流带来不可估计的延迟;
c)、未加密的WebSocket连接(ws://开头的请求)服务器时,如果中间存在透明代理服务器,连接可能会失败,或者发送消息会失败;而加密的WebSocket连接在存在透明代理服务器的情况下成功的机率会比较大;
关于代理详细参见:http://www.infoq.com/cn/articles/Web-Sockets-Proxy-Servers
WebSocket,并非HTML 5独有,WebSocket是一种协议。只是在handshake的时候,发送的链接信息头和HTTP相似。HTML 5只是实现了WebSocket的客户端。其实,难点在于服务端,服务端相对还是比较复杂的。

websocket 的协议在RFC6455中 http://tools.ietf.org/html/rfc6455#section-5.1

目前支持webSocket客户端有Firefox4、Chrome4、Opera10.70以及Safari5等,android手机上的webkit等支持html5的都支持,在客户端除了直接使用websocket的api也可以使用jquery.socket.jsatmosphere.js socket.io等
Java服务器支持webSocket有tomcat 7.0.27, Netty 3.3.x,Jetty 7.x,GlassFish 3.1.2,比她们更高的版本当然也支持了。
基于HTML5和Tomcat WebSocketServlet以及android聊天室简单实现
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String WsBasePath = "ws://" + request.getServerName() + ":"
+ request.getServerPort() + path + "/";
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>websocket聊天室</title>
<style type="text/css">
#chat {
text-align: left;
width: 600px;
height: 500px;
width: 600px;
} #up {
text-align: left;
width: 100%;
height: 400px;
border: 1px solid green;
OVERFLOW-Y: auto;
} #down {
text-align: left;
height: 100px;
width: 100%;
}
</style>
</head>
<body>
<h2 align="center">基于HTML5的聊天室</h2>
<div align="center" style="width: 100%; height: 700px;">
<div id="chat">
<div id="up"></div>
<div id="down">
<textarea style="width: 602px; height: 100%;" id="send"></textarea>
</div>
</div>
<br/>
<input type="button" value="连接" onclick="chat(this);"> <input
type="button" value="发送" onclick="send(this);" disabled="disabled"
id="send_btn" title="Ctrl+Enter发送">
</div>
</body>
<script type="text/javascript">
var socket;
var receive_text = document.getElementById("up");
var send_text = document.getElementById("send");
function addText(msg) {
receive_text.innerHTML += "<br/>" + msg;
receive_text.scrollTop = receive_text.scrollHeight;
}
var chat = function(obj) {
obj.disabled = "disabled";
try{
socket = new WebSocket('<%=WsBasePath + "chat"%>');
receive_text.innerHTML += '<%=WsBasePath + "chat"%>';
receive_text.innerHTML += "<font color=green>正在连接服务器……</font>";
}catch(e){
receive_text.innerHTML += "<font color=red>抱歉,您的浏览器不支持html5,请使用IE10或者最新版本的谷歌、火狐等浏览器!</font>";
}
//打开Socket
socket.onopen = function(event) {
falg=false;
addText("<font color=green>连接成功!</font>");
document.getElementById("send_btn").disabled = false;
send_text.focus();
document.onkeydown = function(event) {
if (event.keyCode == 13 && event.ctrlKey) {
send();
}
};
};
socket.onmessage = function(event) {
addText(event.data);
}; socket.onclose = function(event) {
addText("<font color=red>连接断开!</font>");
obj.disabled = "";
};
};
var send = function(obj) {
if (send_text.value == "") {
return;
}
socket.send(send_text.value);
send_text.value = "";
send_text.focus();
};
</script>
</html>
ChatWebSocketServlet.java
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set; import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest; import org.apache.catalina.websocket.MessageInbound;
import org.apache.catalina.websocket.StreamInbound;
import org.apache.catalina.websocket.WebSocketServlet;
import org.apache.catalina.websocket.WsOutbound; @WebServlet("/chat")
public class ChatWebSocketServlet extends WebSocketServlet { private final Map<Integer, WsOutbound> map = new HashMap<Integer, WsOutbound>();
//private static final long serialVersionUID = -1058445282919079067L;
private static final long serialVersionUID = 911879078000755859L; public class ChatMessageInbound extends MessageInbound { @Override
protected void onBinaryMessage(ByteBuffer arg0) throws IOException {
// TODO Auto-generated method stub } @Override
protected void onTextMessage(CharBuffer arg0) throws IOException {
// TODO Auto-generated method stub
String msg = arg0.toString();
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
msg = " <font color=green>匿名用户 " + sdf.format(date) + "</font><br/> " + msg;
broadcast(msg);
} @Override
protected void onClose(int status) {
// TODO Auto-generated method stub
map.remove(getWsOutbound().hashCode());
super.onClose(status);
} @Override
protected void onOpen(WsOutbound outbound) {
// TODO Auto-generated method stub
map.put(outbound.hashCode(), outbound);
System.out.println("上线" + outbound.hashCode());
super.onOpen(outbound);
} } @Override
protected StreamInbound createWebSocketInbound(String arg0,
HttpServletRequest arg1) {
// TODO Auto-generated method stub
return new ChatMessageInbound();
} private void broadcast(String msg) {
Set<Integer> set = map.keySet();
for (Integer integer : set) {
WsOutbound outbound = map.get(integer);
CharBuffer buffer = CharBuffer.wrap(msg);
try {
outbound.writeTextMessage(buffer);
outbound.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
} }
基于android客户端和websocket协议实现的有autobahn库,包含The WebSocket Protocol and The WebSocket Application Messaging Protocol (WAMP),具体见链接 http://autobahn.ws/android。
package com.example.testwebsocket;
import de.tavendo.autobahn.WebSocketConnection;
import de.tavendo.autobahn.WebSocketConnectionHandler;
import de.tavendo.autobahn.WebSocketException;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu; public class MainActivity extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
System.out.println("开始连接websocket///");
final WebSocketConnection wsc = new WebSocketConnection();
try {
wsc.connect(
"ws://10.204.79.19:8080/chat",
new WebSocketConnectionHandler() { @Override
public void onOpen() {
// TODO Auto-generated method stub
System.out.println("onOpen");
wsc.sendTextMessage("Hello!");
//wsc.disconnect();
// super.onOpen();
} @Override
public void onClose(int code, String reason) {
// TODO Auto-generated method stub
System.out.println("onClose reason=" + reason);
// super.onClose(code, reason);
} @Override
public void onTextMessage(String payload) {
// TODO Auto-generated method stub
System.out.println("onTextMessage" + payload);
// super.onTextMessage(payload);
} @Override
public void onRawTextMessage(byte[] payload) {
// TODO Auto-generated method stub
System.out.println("onRawTextMessage size="
+ payload.length);
// super.onRawTextMessage(payload);
} @Override
public void onBinaryMessage(byte[] payload) {
// TODO Auto-generated method stub
System.out.println("onBinaryMessage size="
+ payload.length);
// super.onBinaryMessage(payload);
} });
} catch (WebSocketException e) {
e.printStackTrace();
} } @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
} }
相关websocket协议实现的android版本库见截图

websocket学习和使用的更多相关文章
- WebSocket学习笔记IE,IOS,Android等设备的兼容性问
WebSocket学习笔记IE,IOS,Android等设备的兼容性问 一.背景 公司最近准备将一套产品放到Andriod和IOS上面去,为了统一应用的开发方式,决定用各平台APP嵌套一个HTML5浏 ...
- WebSocket学习笔记——无痛入门
WebSocket学习笔记——无痛入门 标签: websocket 2014-04-09 22:05 4987人阅读 评论(1) 收藏 举报 分类: 物联网学习笔记(37) 版权声明:本文为博主原 ...
- WebSocket 学习笔记
WebSocket 学习笔记 来自我的博客 因为项目原因需要用到双工通信,所以比较详细的学习了一下浏览器端支持的 WebSocket. 并记录一些遇到的问题. 简介 WebSocket 一般是指浏览器 ...
- WebSocket 学习(三)--用nodejs搭建服务器
前面已经学习了WebSocket API,包括事件.方法和属性.详情:WebSocket(二)--API WebSocket是基于事件驱动,支持全双工通信.下面通过三个简单例子体验一下. 简单开始 ...
- WebSocket学习总结
一 .websocket 已解决 但是websocket延伸出来的网络编程还有好多知识点没有清理.主要的流程和实现方式已经大概了解清楚,下面从学习的进度思路来一点点复习. 网络 ...
- websocket学习和群聊实现
WebSocket协议可以实现前后端全双工通信,从而取代浪费资源的长轮询.在此协议的基础上,可以实现前后端数据.多端数据,真正的实时响应.在学习WebSocket的过程中,实现了一个简化版群聊,过程和 ...
- java websocket学习
引言: websocket,webservice傻傻分不清楚,都觉得是很高深的东西,理解中的webservice是一种协议,通信协议,类似http协议的那种,比如使用webservice协议调后台接口 ...
- WebSocket学习记录
参考资料: Java后端WebSocket的Tomcat实现 基于Java的WebSocket推送 java WebSocket的实现以及Spring WebSocket 利用spring-webso ...
- WebSocket 学习--用nodejs搭建服务器
最简单的socket服务端 var net = require("net"); server1 = net.createServer(function(client){ clien ...
- 【转载】Websocket学习
首先是在Tomcat里面看到Websocket的演示.很有意思. http://localhost:8080/examples/websocket/index.xhtml 里面有: Echo exam ...
随机推荐
- bzoj1013 [JSOI2008]球形空间产生器
Description 有一个球形空间产生器能够在n维空间中产生一个坚硬的球体.现在,你被困在了这个n维球体中,你只知道球面上n+1个点的坐标,你需要以最快的速度确定这个n维球体的球心坐标,以便于摧毁 ...
- 详解Java反射机制
反射是程序在运行状态下,动态的获取某个类的内部信息的一种操作.例如:类名,包名,所有属性的集合,所有方法的集合,构造方法的集合等.该操作发生在程序的运行时状态,所以编译器管不着有关反射的一些代码,通常 ...
- cmd 命令行模式操作数据库 添加查询 修改 删除 ( 表 字段 数据)
一 查看数据库.表.数据字段.数据 1 首先配置环境变量 进入mysql 或者通过一键集成工具 打开mysql命令行 或者mysql 可视化工具 打开命令行 进入这样的界面 不同的机器操作不同 ...
- OAuth 2.0: Bearer Token Usage
Bearer Token (RFC 6750) 用于HTTP请求授权访问OAuth 2.0资源,任何Bearer持有者都可以无差别地用它来访问相关的资源,而无需证明持有加密key.一个Bearer代表 ...
- selenium 远程服务设置
第一步:将浏览器的安装地址以及浏览器的驱动地址添加到系统变量path中.浏览器只需要添加此浏览器exe文件所在的目录就可以,驱动需要添加完整的地址包括驱动本身XXX.exe. 第二步:需要安装jdk环 ...
- httpd配置ResponseHeader
今天遇到一个问题:我把项目编译后的静态文件发布到开发机上,开发机使用httpd启的静态文件服务,页面的访问是在特制的壳浏览器里面,我更新了代码后,发现页面被缓存了,找到壳的RD联调了一下,发现我的主页 ...
- SVN提交后自动推送消息到钉钉群
钉钉设置机器人配置 1.进入配置机器人入口 2.添加机器人 3.测试WebHook请求 本人使用Postman进行测试 4.配置SVN 4.1 配置 Pre-commit hook 设置提交内容必须包 ...
- Oracle之分组函数嵌套以及表连接
--1 数据环境准备 scott 用户下面的emp,dept表 --2 要求 :求平均工资最高的部门编号,部门名称,部门平均工资 select d.deptno,d.dname,e.salfrom(s ...
- 【基础】新手任务,五分钟全面掌握JQuery选择器
1. 基本选择器 1.1 ID选择器: //选中id为myDiv的元素,速度最快 $("#myDiv") 1.2 类选择器: //选中class属性为red的所有元素 $(&quo ...
- 对JVM运行时常量池的一些理解
1.JVM运行时常量池在内存的方法区中(在jdk8中,移除了方法区) 2.JVM运行时常量池中的内容主要是从各个类型的class文件的常量池中获取,对于字符串常量,可以调用intern方法人为添加,而 ...