博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
websocket学习和使用
阅读量:7118 次
发布时间:2019-06-28

本文共 8081 字,大约阅读时间需要 26 分钟。

1WebSocket介绍 

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请求及销毁请求,减少网络带宽资源的占用,同时也节省服务器资源;

 3WebSocket数据帧的介绍

a)、草案版本00到草案版本05之间,详细可以查看草案文档,解码编码可以看见NettyWebSocketFrameDecoderWebSocketFrameEncoder实现;

b)、草案版本06到现在最新的草案17,介绍参见文章:

4WebSocket不同版本的几种握手方式

a)、无安全key、最老的WebSocket握手协议的实现(Flash);
b
)、带两个安全key请求头的后端握手实现;
c
)、带一个安全key请求头的后端握手实现;

参见:

5WebSocket可以穿越防火墙吗?

WebSocket使用标准的80443端口,这两个都是防火墙友好协议,Web Sockets使用HTTP Upgrade机制升级到Web Socket协议。HTML5 Web Sockets有着兼容HTTP的握手机制,因此HTTP服务器可以与WebSocket服务器共享默认的HTTPHTTPS端(80443)。

6)、Web Sockets与代理服务器交互

代理服务器的问题:
a
)、HTTP代理服务器可能会选择关闭流或闲置的WebSocket连接,因为它们看起好像是尝试连接一个没有回应的HTTP服务器;
b
)、代理服务器可能会缓冲未加密的HTTP响应,这将会对HTTP响应流带来不可估计的延迟;
c
)、未加密的WebSocket连接(ws://开头的请求)服务器时,如果中间存在透明代理服务器,连接可能会失败,或者发送消息会失败;而加密的WebSocket连接在存在透明代理服务器的情况下成功的机率会比较大;

关于代理详细参见: 

 

WebSocket,并非HTML 5独有,WebSocket是一种协议。只是在handshake的时候,发送的链接信息头和HTTP相似。HTML 5只是实现了WebSocket的客户端。其实,难点在于服务端,服务端相对还是比较复杂的。 

 

websocket 的协议在RFC6455中  

 

目前支持webSocket客户端有Firefox4Chrome4Opera10.70以及Safari5等,android手机上的webkit等支持html5的都支持,在客户端除了直接使用websocketapi也可以使用jquery.socket.jsatmosphere.js socket.io

Java服务器支持webSockettomcat 7.0.27, Netty 3.3.x,Jetty 7.x,GlassFish 3.1.2,比她们更高的版本当然也支持了。

基于HTML5Tomcat 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库,包含 and ,具体见链接

 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版本库见截图

 

 

 

 

转载于:https://www.cnblogs.com/wangtale/p/3246000.html

你可能感兴趣的文章
险些被吓到!白宇代言新品万元荣耀8X售价原因揭秘
查看>>
冲动是魔鬼!国庆换机如何不花冤枉钱?
查看>>
杭州街头惊现“梦想改造家”,ATM取款区变废为宝
查看>>
百度Apollo发布智能驾驶商业化解决方案
查看>>
2018年预测:GPU数据库或是未来的数据库统治者!
查看>>
「每天一道面试题」谈String和StringBuffer、StringBuilder区别
查看>>
统计局:去年12月天然气、电力生产增长较快
查看>>
房租抵扣个税不用再填房东信息 房东这下放心了吗?
查看>>
大湾区足球联赛港澳赛区上演进球大战
查看>>
又一巨头布局区块链,360区块猫上线,你不想拥有一只零代猫吗
查看>>
[译] Scala 类型的类型(一)
查看>>
Swift iOS : 代码分析DrawController
查看>>
Architecture(5)电商APP组件化探索
查看>>
Web全屏模式轻松掌握[局部元素全屏展示]
查看>>
超详细的Java面试题总结(三)之Java集合篇常见问题
查看>>
BCH升级在即,什么是OP_CHECKDATASIG和Canonical Transaction Ordering(一)
查看>>
Vue 中实现双向绑定的 4 种方法
查看>>
关闭tomcat报错Cannot allocate memory
查看>>
深圳行:1207-Day 1 - 到达
查看>>
mysqls为node.js而编写的sql语句生成插件 crud for mysql.
查看>>