HTML5   发布时间:2022-04-25  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了HTML5下的WebSocket学习笔记大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

基础知识


1.WebSocket API   --- 基于JavaScript,包括 WebSocket原始对象,事件,方法属性,通过WebSocket API可以连接到本地货远程的Server服务器,发送和接收消息,关闭连接
2.使用WebSocket的典型流程:
   1.检查浏览器是否支持WebSocket                 --- Check for WebSocket browser support
   2.创建WebSocket的js对象                       --- Create an instance of the WebSocket JS Object
   3.连接WebSocket服务器                         --- Connect to the WebSocket Server
   4.注册WebSocket事件                           --- Register for the WebSocket events
   5.根据用户交互进行数据传输                    --- Perform the proper data transmission according to users' actions
   6.关闭连接                                    --- Close the connection


   1.Browser Support ---  检测浏览器是否支持WebSocket
       if(window.WebSocket){
       console.log("WebSocket supported");
       //通过WebSocket进行操作
       }else{
       //不支持WebSocket,给出相应的提示和处理策略
       alert("Consider updating your browser for a richer experience");
       }

   2.The WebSocket Object    --- WebSocket的JavaScript对象     new WebSocket(url)   --- url:表示WebSocket要连接的服务器
       var socket = new WebSocket("ws://echo.websocket.org");
     说明:
          当创建一个WebSocket的JS对象后,它会立即连接到指定的服务器

   3.WebSocket 事件        --- WebSocket Events
      WebSocket的四个主要事件:
                              事件              对应方法
                              Open              onopen
                              Message           onmessage
                              Close             onclose
                              Error             onerror

            事件处理的两种方式
            1.通过事件的对应方法     ---  推荐:简单结构清晰
            2.addEventListener方法去实现事件处理

      说明:当不同的事件发生时,会触发相应的方法,执行逻辑代码

   4.WebSocket的事件处理

      onopen      --  事件在连接成功时触发,达成第一个握手,准备传输数据
         eg:
           socket.onopen = function(event){
             console.log("Connection established");
             //在这类可以初始化资源,并展示一些用户友好提示信息
             var label = document.getElementById("status-label");
             label.innerHTML="Connection established";
           }


      onmessage   -- 数据传输事件,客户端随时监听Server,当服务器端发送给客户端数据时触发  --- 数据包括:文本、图片、二进制数据等
         eg:
           socket.onmessage = function(event){
             console.log("Data received");
             if(typeof event.data == "string"){
             var label = document.getElementById("status-label");
             label.innerHTML = event.data;
             }
           }


      onclose    --  关闭客户端与服务器的连接,不能在进行数据的传输。
                     关闭连接的原因有多种:服务器关闭,客户端调用close()方法关闭,或者TCP错误  --- 可通过 code,reason,wasClean参数检测连接关闭的原因
                     code    ---    用一个唯一的数字,表示连接中断的原因
                     reason  ---    连接中断的原因
                     wasClean  ---  用于判断连接关闭,是因为服务器的原因,还是未知的网络错误
         eg:
           socket.onclose = function(event){
           console.log("Connections closed");
           var code = event.code;
           var reason = event.reason;
           var wasClean = event.wasClean;

           var label = document.getElementById("status-label");

           if(wasClean){
               label.innerHTML = "Connection closed normally";
           }else{
               label.innerHTML ="Connection closed with message "+reason+"(Code: "+code+")";
           }
           }


      onerror    --  出错时触发的事件,该事件出发后,会接着触发close事件,终止连接  ---  注意出错时给出提示,并尝试重新建立连接
         eg:
           socket.onerror = function(event){
              console.log("Error occurred");
              //出错提示
              var label = document.getElementById("status-label");
              label.innerHTML = "Error: "+event;
           }

   5.WebSocket的操作处理Actions  即:处理方法
            两种  send()和close()

         1.send()    ---    当连接成功后,客户端可与服务端进行数据传输,send()方法用于传输数据到服务器
             eg:
                var textView = document.getElementById("text-view");
                var buttonSend = document.getElementById("send-button");
                buttonSend.onClick = function(){
                //发送数据
                if(socket.readyState == WebSocket.OPEN){
                socket.send(textView.value);
                }
                }
         特别注意:
                 只有在连接成功时才能发送数据,因此,要么把send()方法放在onopen事件中处理,要么在发送数据是进行判断:当前连接是否成功


         2.close()   ---   中断连接
              eg:
                 通过点击按钮事件来中断当前连接
                   var textView = document.getElementById("text-view");
                   var buttonStop = document.getElementById("stop-button");
                   buttonSend.onClick = function(){
                   if(socket.readyState == WebSocket.OPEN){
                      socket.close();
                      //也可之前提到的传递code和reason参数
                      //socket.close(1000,"Deliberate disconnection");
                   }
                   }


   6.WebSocket的属性  Properties
        url          ---  返回WebSocket的URL
        protocol     ---  返回Server服务器使用的协议
        readyState   ---  连接状态
                                  WebSocket.OPEN           --- 已连接
                                  WebSocket.CLOSED         --- 已关闭
                                  WebSocket.CONNECTING     --- 正在连接
                                  WebSocket.CLOSING        --- 正在关闭
        bufferedAmount   ---  返回send()方法调用时,已进入队列但尚未发送到服务器的总字节数
        binaryType       ---  返回接收到的二进制数据  -- (onmessage事件被触发时)

   7.WebSocket的Server
       1.流程
          Server                                                               Client
          Create a server on localhost:8080
          Start running
          initial handshake: establish connection       <------------          Request connection
          Handle the incoming message                   <------------          Send message

       2.Server处理
           1.初始化WebSocket的地址
           2.处理客户端的各类事件   OnOpen,OnClose,OnMessage,以及向客户端发送数据

       3.使用Java实现的WebSocket服务器   --- 需要JDK1.7+
                                         --- 需要Tomcat7+下的lib中Tomcat-websocket.jar和websocket-api.jar

       完整的例子  WebSocketTest1.java

       package com.jay.websocket;

       import javax.websocket.OnClose;
       import javax.websocket.OnMessage;
       import javax.websocket.OnOpen;
       import javax.websocket.Session;
       import javax.websocket.server.ServerEndpoint;
       import java.io.IOException;

       /**
        * Java 实现的WebSocket服务器,* 实现客户端的onopen,onmessage,onclose事件的处理方法
        *  @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义一个websocket服务器端。注解的值将被用于监听用户连接的终端访问URL地址。
           onOpen 和 onClose 方法分别被@OnOpen和@OnClose 所注解。这两个注解的作用不言自明:他们定义了当一个新用户连接和断开的时候所调用方法。
           onMessage 方法被@OnMessage所注解。这个注解定义了当服务器接收到客户端发送的消息时所调用方法。注意:这个方法可能包含一个javax.websocket.Session可选参数(在我们的例子里就是session参数)。如果有这个参数,容器将会把当前发送消息客户端的连接Session注入进去。
           本例中我们仅仅是将客户端消息内容打印出来,然后首先我们将发送一条开始消息,之后间隔5秒向客户端发送1条测试消息,共发送3次,最后向客户端发送最后一条结束消息。
        * Created by Jay He on 2015/9/19.
        */
       @ServerEndpoint("/websocket")
       public class WebSocketTest1 {

           /**
            * 这里用于接收客户端的数据和发送给客户端数据
            * @param message
            * @param session
            * @throws IOException
            * @throws InterruptedException
            */
           @OnMessage
           public void onMessage(String message,Session session)
                   throws IOException,InterruptedException {

               // Print the client message for testing purposes
               System.out.println("Received: " + message);

               // Send the first message to the client
               session.getBasicRemote().sendText("This is the first server message");

               // Send 3 messages to the client every 5 seconds
               int sentMessages = 0;
               while(sentMessages < 3){
                   Thread.sleep(5000);
                   session.getBasicRemote().
                           sendText("This is an intermediate server message. Count: "
                                   + sentMessages);
                   sentMessages++;
               }

               // Send a final message to the client
               session.getBasicRemote().sendText("This is the last server message");
           }

           //客户端连接
           @OnOpen
           public void onopen() {
               System.out.println("Client connected");
           }

           //断开连接
           @OnClose
           public void onClose() {
               System.out.println("Connection closed");
           }
       }

       页面显示:websocket.html

       <!DOCTYPE html>
       <html>
       <head lang="en">
           <Meta charset="UTF-8">
           <title>Testing WebSocket</title>
       </head>
       <body>
       <div>
           <input type="submit" value="点击请求WebSocket服务器" onclick="start()" />
       </div>
       <div id="messages"></div>
       <script type="text/javascript">
           var webSocket =
                   new WebSocket('ws://localhost:8080/JayEEDemo1/websocket');

           webSocket.onerror = function(event) {
               onError(event)
           };

           webSocket.onopen = function(event) {
               onOpen(event)
           };

           webSocket.onmessage = function(event) {
               onMessage(event)
           };

           function onMessage(event) {
               document.getElementById('messages').innerHTML
                       += '<br />' + event.data;
           }

           function onOpen(event) {
               document.getElementById('messages').innerHTML
                       = 'Connection established';
           }

           function onError(event) {
               alert(event.data);
           }

           function start() {
               webSocket.send('hello');
               return false;
           }
       </script>
       </body>
       </html>


   8.使用WebSocket传输不同类型的数据
                                      文本文件(String)和二进制文件(ArrayBuffer或Blob)
                                      特别注意:WebSocket传输二进制文件时,只能选择ArrayBuffer或Blob中的一种,不能混用
                                      eg:
                                         ArrayBuffer方式:
                                                    socket.binaryType="arraybuffer";
                                         Blob方式:
                                                    socket.binaryType="blob";
        1.文本文件传输  --- 根据typeof event.data判断类型
              1.String
                         socket.onmessage=function(event){
                         if(typeof event.data=="string"){
                         console.log("Received string data");
                         }
                         }
              2.JSON
                         if(typeof event.data=="string"){
                         //创建JSON对象
                         var jsonObject = JSON.parse(event.data);
                         //根据key获取JSON值
                         var username=jsonObject.name;
                         var userMessage = jsonObject.message;
                         }

        2.二进制文件传输
              1.ArrayBuffer  --- 用于传输小型二进制文件图片等
                  1.发送二进制文件

                        通过拖拽事件,处理图片,每次拖进一条图片,通过js的FileReader来读取文件生成一个ArrayBuffer,
                        当reader处理完file后,在onload事件中,使用WebSocket将数据发送给服务器

                        1.通过ArrayBuffer方式发送图片给服务器
                        document.ondrop = function(event){
                          var file = event.dataTransfer.files[0];
                          var reader = new FileReader();
                          reader.readAsArrayBuffer(file);
                          reader.onload = function(){
                             socket.send(reader.result);
                          }
                          return false;
                        }

                        2.通过Blob方式发送图片给服务器
                        document.ondrop = function(event){
                        var file = event.dataTransfer.files[0];
                        //直接发送以blob方式
                        socket.send(file);
                        return false;
                        }

                  特别说明:
                           使用浏览器的拖拽事件时,要自定义方法,覆盖浏览器认的事件处理,防止浏览器认事件处理影响自己写的处理方法
                           eg:
                             //覆写拖动对象事件
                             document.ondragover = function(event){
                             event.preventDefault();
                             }

                         说明:
                              dragStart      ---  拖动开始
                              dragOver       ---  停放位置
                              drop           ---  拖动结束


                  2.接收二进制文件

                          js接收二进制文件时,通过instanceof判断是否是ArrayBuffer
                          socket.onmessage = function(event){
                           if(event.data instanceof ArrayBuffer){
                             var buffer = event.data;
                           }
                          }

              2.Blobs     ---   用于传输大的二进制文件,视频和其他二进制大文件等
                          需要在展示时判断Server传递过来的是否是Blob

                          eg:通过blob形式接收Server传递的图片
                            socket.message=function(event){
                            if(event.data instanceof blob){
                            //1.获取二进制文件
                            var blob = event.data;
                            //2.为Blob对象创建新的URL
                            window.URL = window.URL || window.webkitURL;
                            var source = window.URL.createObjectURL(blob);
                            //3.创建image标签
                            var image = document.createElement("img");
                            image.src = source;
                            image.alt = "Image generated from blob";
                            //4.将创建的标签插入到document尾部
                            document.body.appendChild(image);
                            }
                            }

                          eg:通过blob接收视频流   --   Video的本质是连续的图片,又帧组成后形成了视频
                            <img id="video" src="" alt="Video streaming"/>

                            var video = document.getElementById("video");
                            socket.onmessage = function(event){
                            if(event.data instanceof Blob){
                            //1.获取二进制数据
                            var blob = event.blob;
                            //2.为blog对象创建新的的URL
                            window.URL = window.URL || window.webkitURL;
                            var source = window.URL.createObjectURL(blob);
                            //3.更新资源
                            video.src = source;
                            //4.释放申请的内存
                            window.URL.revokeObjectURL(source);
                            }
                            }

                          代码说明:
                            1.类似上一个图片传输,但这里预先在html中引用了一个<img>标签,在通讯时,不停的改变其src属性
                            2.每次设置src后,通过revokeObject方法释放URL所在内存


              3.通过JSON传递数据
                          eg:
                            <label id="status-label">Status...</label>
                            <input type="text" id="name-view" placeholder="Your name" />
                            <input type="text" id="text-view" placeholder="Type your message..." />
                           js:
                              发送JSON数据
                              var nameView = document.getElementById("name-view");
                              buttonSend.onclick = function(event){
                              if(socket.readyState == WebSocket.OPEN){
                              //构造json,并发送
                              var json = "{'name':'"+nameView.value+"','message':'"+textView.value+"'}";
                              socket.send(json);
                              textView.value="";
                              }
                              }

                            接收服务端的JSON数据
                              socket.onmessage = function(event){
                              if(typeof event.data == "String"){
                              //显示信息
                              var jsonObject = eval('('+event.data+')');
                              var userName = jsonObject.name;
                              var userMessage = jsonObject.message;
                              chatArea.innerHTML = charArea.innerHTML+"<p><strong>"+userName+"</strong>:"+userMessage+"</p>"
                              }
                              }


   9.WebSocket的安全问题:
       客户端发送的Header
       The following is an example of WebSocket header sent from a client:
       GET /chat HTTP/1.1
       Host: server.example.com
       Upgrade: websocket
       Connection: Upgrade
       Origin: http://example.com
       Pragma: no-cache
       Cache-Control: no-cache
       Sec-WebSocket-Key: AAf/gvkPw6szicrMH3Rwbg==
       Sec-WebSocket-Version: 13
       Sec-WebSocket-Extensions: x-webkit-deflate-frame

       服务器端返回的Header
       HTTP/1.1 101 Switching Protocols
       Upgrade: websocket
       Connection: Upgrade
       Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=


      常见的攻击类型:
      DoS攻击(Denial of Service)  拒绝服务攻击,通过一定的手段使得请求资源对用户不可用     eg:循环攻击,导致服务器繁忙或无法响应
      中间人攻击(Man-in-the-middle),通常是信息未加密导致
      XSS跨站脚本攻击  ,通过植入脚本实现攻击,让脚本在客户端机器上执行      ---  通过传输数据的转码可以避免这类攻击


     WebSocket协议自带的   wss  可保证安全的传输,防止入侵


   10.异常的处理与反馈
                 1.浏览器的支持问题
                 2.不支持的浏览器,通过一定技术手段去完成WebSocket的处理  eg:socketio.js

      常见的错误处理:
             1.内部异常
                      能够控制的代码或逻辑异常
             2.外部异常
                      网络连接问题    ---   检查网络可用性      通过HTML5的navigator对象,判断网络是否可用
                     eg:1.检查网络可用性
                       if(navigator.onLine){
                       alert("You are OnLine");
                       }else{
                       alert("You are OffLine");
                       }
                     eg:2.通知用户网络不可用,并尝试重新连接
                       socket.onclose = function(event){
                       //先检测原因,再重新连接
                       if(event.code!=1000){
                       //event.code==1000表示是连接正常关闭
                       if(!navigator.onLine){
                       alert("You are offline. Please connect to the Internet and try again");
                       }
                       }
                       }

      处理浏览器HTML5不支持的问题
            使用polyfills方案的插件库,来解决老版本浏览器不支持HTML5的问题
            常用的js库: sockJS,socket.io和jQuery的插件库  Graceful WebSocket   ---  https://github.com/ffdead/jquery-graceful-websocket
            eg:
               使用Graceful WebSocket库,来实现HTML5的功能
               1.引入两个库
                <script src=" jquery-1.9.1.min.js"></script>
                <script src="jquery.gracefulWebSocket.js"></script>
               2.使用 $.gracefulWebSocket(address) 代替 new WebSocket(address) 创建WebSocket对象
                 var socket = $.gracefulWebSocket("ws://localhost:8181")
               3.实现4个常用事件函数
                 socket.onopen = function(event){
                 //处理连接事件
                 }
                 socket.onclose = function(event){
                 //处理连接关闭事件
                 }
                 socket.onmessage = function(event){
                 //处理消息接收事件
                 }
                 socket.onerror = function(event){
                 //处理异常事件
                 }

                 发送消息:
                 socket.send("Hello server! I'm a WebSocket polyfill.");



一个WebSocket的实践:
                    HTML5 WebSocket实现实时视频文字传输

     客户端
           <!DOCTYPE html>

           <html xmlns="http://www.w3.org/1999/xhtml">
           <head>
               <title></title>
               <script type="text/javascript">
                   //1.初始化WebSocket对象
                   var webSocket = new WebSocket("ws://localhost:8080/webSocket");
                   //向服务器发送消息
                   //webSocket.send("hell0");
                   //查看WebSocket当前状态
                   //alert(webSocket.readyState);

                   //2.定义WebSocket的事件方法
                   webSocket.onopen = function(event){
                   alert("已经建立连接");
                   }
                   webSocket.onmessage = function(event){
                   //收到服务器消息,使用event.data提取消息内容   -- 可以是文本,也可能是二进制文件
                   writeToScreen(event.data);
                   }
                   webSocket.onclose = function(event){
                   alert("已经关闭连接");
                   }
                   webSocket.onerror = function(event){
                   alert("产生异常");
                   //将异常信息打印在屏幕上
                   writeToScreen(event.message);
                   }

                   //发送消息给服务器
                   function sendMsg(){
                   if(webSocket.readyState == WebSocket.OPEN){
                   msg = document.getElementById("msg").value;
                   webSocket.send(msg);
                   writeToScreen("发送成功!");
                   }else{
                   writeToScreen("发送失败!");
                   }
                   }

                   //将信息写到屏幕
                   function writeToScreen(message){
                   var pre = document.createElement("p");
                   pre.style.wordWrap="break-word";
                   pre.innerHTML+=message;
                   output.appendChild(pre);
                   }

               </script>
           </head>
           <body>
               <div>
                   <input type="text" id="msg" value="beyond is number one!" />
                   <button onclick="sendMsg()">send</button>
               </div>
               <div id="output"></div>
           </body>
           </html>

           代码说明:
              1.readyState表示的四种状态:
                         CONNECTING(0)          --- 还未建立连接
                         OPEN(1)                --- 已建立连接,可进行通讯
                         CLOSING(3)             --- 正在关闭连接
                         CLOSED(4)              --- 连接已经关闭或无法打开
              2.WebSocket的协议,通常是  ws  或  wss(加密通信)
              3.send()方法将数据发送到服务器端
              4.close()方法关闭连接
              5.几个触发事件:
                       onopen          ---   连接建立,即:握手成功触发的事件
                       onmessage       ---   收到服务器消息时触发的事件
                       onerror         ---   异常触发的事件
                       onclose         ---   关闭连接触发的事件




     服务器端


基于WebSocket的即时通讯:

Server端

<pre>import java.io.IOException;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;

import javax.websocket.CloseReason;
import javax.websocket.CloseReason.CloseCodes;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.RemoteEndpoint;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
//注意此访问地址格式如:"ws://"+ window.location.host+"/${pageContext.request.contextPath}/game"是ws开头的,而不是以http:开头的.
@ServerEndpoint(value = "/game")
public class Scoket {

    private Logger logger = Logger.getLogger(this.getClass().getName());

    static Map<String,Session> sessionMap = new Hashtable<String,Session>();
    
    @OnOpen
    public void onOpen(Session session) {
    	sessionMap.put(session.getId(), session);
    }

    @OnMessage
    public void onMessage(String unscrambledWord, Session session) {
    	broadcastAll("message",unscrambledWord);
    }
    /**
     * 广播给所有人
     * @param message
     */
    public static void broadcastAll(String type,String message){
        Set<Map.Entry<String,Session>> set = sessionMap.entrySet();
        for(Map.Entry<String,Session> i: set){
            try {
            	i.getValue().getBasicRemote().sendText("{type:'"+type+"',text:'"+message+"'}");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @OnClose
    public void onClose(Session session, CloseReason closeReason) {
    	sessionMap.remove(session.getId());
        logger.info(String.format("Session %s closed because of %s", session.getId(), closeReason));
    }
    
    @OnError
    public void error(Session session, java.lang.Throwable throwable){
    	sessionMap.remove(session.getId());
        System.err.println("session "+session.getId()+" error:"+throwable);
    }
}

 注解说明: 

                @ServerEndpoint                  将POJO转换为服务器端点

                @ClientEndpoint                   将Pojo转换为客户端端点

                @OnMessage                        处理WebSocket的onMessage事件

                @PathParam                          方法参数,标记匹配的URI模板路径

                @OnOpen                               处理WebSocket的open事件

                @OnClose                               处理WebSocket的close事件

                @OnError                                 处理WebSocket的error事件

                

Client端

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<Meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script src="http://lib.sinaapp.com/js/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
var socket =null;
$(function(){
	function parSEObj(strData){//转换对象
	    return (new Function( "return " + strData ))();
	};
	//创建socket对象
	socket = new WebSocket("ws://"+ window.location.host+"/${pageContext.request.contextPath}/game");
	//连接创建后调用
	socket.onopen = function() {
		$("#showMsg").append("连接成功...<br/>");
	};
	//接收到服务器消息后调用
	socket.onmessage = function(message) {
		var data=parSEObj(message.data);
		if(data.type=="message"){
			$("#showMsg").append("<span style='display:block'>"+data.text+"</span>");
		}else if(data.type=="background"){
			$("#showMsg").append("<span style='display:block'>系统改变背景地址,背景地址是:"+data.text+"</span>");
			$("body").css("background","url("+data.text+")");
		}
	};
	//关闭连接的时候调用
	socket.onclose = function(){
		alert("close");
	};
	//出错时调用
	socket.onerror = function() {
		alert("error");
	};
	$("#sendButton").click(function() {
		socket.send($("#msg").val());
	});
	$("#abcde").click(function(){
		$.post("${pageContext.request.contextPath}/backgroundimg");
	});
});
</script>
</head>
<body>
	<div id="showMsg" style="border: 1px solid; width: 500px; height: 400px; overflow: auto;"></div>
	<div>
		<input type="text" id="msg" /> 
		<input type="button" id="sendButton" value="发送" />
		<input type="button" value="改变背景" id="abcde" />
	</div>
</body>
</html>

大佬总结

以上是大佬教程为你收集整理的HTML5下的WebSocket学习笔记全部内容,希望文章能够帮你解决HTML5下的WebSocket学习笔记所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签: