温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

WebSocket协议的作用是什么

发布时间:2021-06-18 14:50:56 来源:亿速云 阅读:531 作者:Leah 栏目:大数据

WebSocket协议的作用是什么,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

WebSocket 是什么?

WebSocket 是一种网络通信协议。RFC6455 定义了它的通信标准。

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

为什么需要 WebSocket ?

了解计算机网络协议的人,应该都知道:HTTP 协议是一种无状态的、无连接的、单向的应用层协议。它采用了请求/响应模型。通信请求只能由客户端发起,服务端对请求做出应答处理。

这种通信模型有一个弊端:HTTP 协议无法实现服务器主动向客户端发起消息。

这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。大多数 Web 应用程序将通过频繁的异步 JavaScript 和 XML(AJAX)请求实现长轮询。轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。

因此,工程师们一直在思考,有没有更好的方法。WebSocket 就是这样发明的。WebSocket 连接允许客户端和服务器之间进行全双工通信,以便任一方都可以通过建立的连接将数据推送到另一端。WebSocket 只需要建立一次连接,就可以一直保持连接状态。这相比于轮询方式的不停建立连接显然效率要大大提高。

WebSocket的通信原理和机制

既然是基于浏览器的web技术,那么它的通信肯定少不了HTTP,websocket本身虽然也是一种新的应用层协议,但是它也不能够脱离HTTP而单独存在。

具体来说,我们在客户端构建一个websocket实例,并且为它绑定一个需要连接到的服务器地址,当客户端连接到服务端的时候会向服务端发送一个类似下面的HTTP报文:

WebSocket协议的作用是什么

可以看到,这是一个HTTP的get请求报文,注意该报文中有一个upgrade首部,它的作用是告诉服务端需要将通信协议切换到websocket。如果服务端支持websocket协议,那么它就会将自己的通信协议切换到websocket,同时发给客户端类似于以下的一个响应报文头:

WebSocket协议的作用是什么

返回的状态码为101,表示同意客户端协议转换请求,并将它转换为websocket协议。以上过程都是利用HTTP通信完成的,称之为websocket协议握手。

经过这握手之后,客户端和服务端就建立了websocket连接,以后的通信走的都是websocket协议了。所以总结为:websocket握手需要借助于HTTP协议,建立连接后通信过程使用websocket协议。

同时需要了解的是,该websocket连接还是基于我们刚才发起HTTP连接的那个TCP连接,一旦建立连接之后,我们就可以进行数据传输了。在websocket中,提供两种数据传输:文本数据和二进制数据。

基于以上分析,我们可以看到,websocket能够提供低延迟,高性能的客户端和服务端的双向数据通信。它颠覆了之前web开发的请求处理响应模式,并且提供了一种真正意义上的客户端请求,服务器推送数据的模式,特别适合实时数据交互应用开发

WebSocket 客户端

<!DOCTYPE HTML>
<html>
   <head>
   <meta charset="utf-8">
   <title>菜鸟教程(runoob.com)</title>
    
      <script type="text/javascript">
      WebSocketTest();
         function WebSocketTest()
         {
            if ("WebSocket">

客户端 API

以下 API 用于创建 WebSocket 对象。

var Socket = new WebSocket(url, [protocol] );

以上代码中的第一个参数 url, 指定连接的 URL。第二个参数 protocol 是可选的,指定了可接受的子协议。

WebSocket 属性

以下是 WebSocket 对象的属性。假定我们使用了以上代码创建了 Socket 对象:

属性描述
Socket.readyState只读属性 readyState 表示连接状态,可以是以下值:0 - 表示连接尚未建立。1 - 表示连接已建立,可以进行通信。2 - 表示连接正在进行关闭。3 - 表示连接已经关闭或者连接不能打开。
Socket.bufferedAmount只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数。
WebSocket 事件

以下是 WebSocket 对象的相关事件。假定我们使用了以上代码创建了 Socket 对象:

事件事件处理程序描述
openSocket.onopen连接建立时触发
messageSocket.onmessage客户端接收服务端数据时触发
errorSocket.onerror通信发生错误时触发
closeSocket.onclose连接关闭时触发
WebSocket 方法

以下是 WebSocket 对象的相关方法。假定我们使用了以上代码创建了 Socket 对象:

方法描述
Socket.send()使用连接发送数据
Socket.close()关闭连接

WebSocket 服务端

package com.gaofei.servlet;

import javax.servlet.http.HttpServletRequest;

import org.apache.catalina.websocket.StreamInbound;
import org.apache.catalina.websocket.WebSocketServlet;

import com.gaofei.entry.MyMessageInbound;

public class DemoServlet extends WebSocketServlet{

	private static final long serialVersionUID = -4853540828121130946L;
    /*
     * (non-Javadoc)
     * 创建一个webSocekt对象,第一个参数表示协议,第二个参数httqrequest对象
     * @see org.apache.catalina.websocket.WebSocketServlet#createWebSocketInbound(java.lang.String, javax.servlet.http.HttpServletRequest)
     *  返回一个绑定的消息
     */
    
    @Override
    protected StreamInbound createWebSocketInbound(String str,HttpServletRequest req) {
    	System.out.println( req.getRemoteAddr());
    	System.out.println(str);
        return new MyMessageInbound();
    }
  


}
package com.gaofei.entry;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;

import org.apache.catalina.websocket.MessageInbound;
import org.apache.catalina.websocket.WsOutbound;

public class MyMessageInbound  extends MessageInbound{
	 WsOutbound wsOutbount;//用于向客户端发送数据对象
	@Override
	protected void onBinaryMessage(ByteBuffer arg0) throws IOException {//接收数据触发,二进制消息文件
		// TODO Auto-generated method stub
		
	}

	@Override
	protected void onTextMessage(CharBuffer message) throws IOException {//接收数据触发,文本消息文件
           System.out.println("收到文本消息:"+message);
           int i=1;
           Long ms0=System.currentTimeMillis()/10000;
           for(;i>0;i++) {
        	   Long ms01=System.currentTimeMillis()/1000;
        	   Long ms01_0=ms01-ms0;
        	   if(ms01_0>10) {
        		   wsOutbount.writeTextMessage(CharBuffer.wrap(i+"来了")); //客户端发送的数据
        		   ms0=System.currentTimeMillis()/1000;
        	   }
           }
	}
    @Override
    protected void onClose(int status) {//断开连接触发
    	// TODO Auto-generated method stub
    	super.onClose(status);
    	System.out.println("断开握手");
    }
    @Override
    protected void onOpen(WsOutbound outbound) {//连接成功触发
    	
    	super.onOpen(outbound);
    	System.out.println("握手成功");
    	this.wsOutbount=outbound;
    	try {
			this.wsOutbount.writeTextMessage(CharBuffer.wrap("你好啊!"));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }
}

pom 配置文件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>om.gaof.webSocketServer</groupId>
  <artifactId>webSocketServer</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
  
	  <dependencies>
	<dependency>
		<groupId>org.apache.tomcat</groupId>
			<artifactId>tomcat-catalina</artifactId>
			<version>7.0.39</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.tomcat</groupId>
			<artifactId>tomcat-coyote</artifactId>
			<version>7.0.39</version>
			<scope>provided</scope>
		</dependency>
	</dependencies>
	
	<build>
	    <finalName>websocketServer</finalName>
	      <plugins>           
        <!-- java编译插件 -->
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.2</version>
            <configuration>
                <!-- 指定端口 -->
                <port>8080</port>
                <!-- 请求路径 -->
                <path>/</path>
            </configuration>                
        </plugin>
    </plugins>
	</build>
</project>

web.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>wsServlet</servlet-name>
<servlet-class>com.gaofei.servlet.DemoServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>wsServlet</servlet-name>
<url-pattern>/wsServlet</url-pattern>
</servlet-mapping>
</web-app>

WebSocket 代理

如果把 WebSocket 的通信看成是电话连接,Nginx 的角色则像是电话接线员,负责将发起电话连接的电话转接到指定的客服。

Nginx 从 1.3 版开始正式支持 WebSocket 代理。如果你的 web 应用使用了代理服务器 Nginx,那么你还需要为 Nginx 做一些配置,使得它开启 WebSocket 代理功能。

以下为参考配置:

server {
  # this section is specific to the WebSockets proxying
  location /socket.io {
    proxy_pass http://app_server_wsgiapp/socket.io;
    proxy_redirect off;

    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 600;
  }
}

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注亿速云行业资讯频道,感谢您对亿速云的支持。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI