Nginx 配置WSS 解析与实战

1. 几个关键概念

1.1 WebSocket

WebSocket 协议是 html5 的一种通信协议,该协议兼容我们常用的浏览器。例如:Chrome、Firefox、IE 等。它可以使客户端和服务端双向数据传输更加简单快捷,并且在TCP连接进行一次握手后,就可以持久性连接,同时允许服务端对客户端推送数据。外加传统模式的协议一般HTTP轻轻可能会包含较长的头部,但真正有效的可能只有小部分,从而占用了很多资源和宽带。因此WebSocket协议不仅可以实时通讯,支持扩展;也可以压缩节省服务资源和宽带。 关于WebSocket的深入理解,可以看这篇文章:Html5 WebSocket 。

WS 协议 和 WSS 协议两个均是 WebSocket 协议的 SCHEM,两者一个是非安全的,一个是安全的。也是统一的资源标志符。就好比 HTTP协议 和 HTTPS协议的差别。非安全的没有证书,安全的需要 SSL 证书。其中 WSS 表示在 TLS 之上的 WebSocket。

WS 一般默认是 80 端口,而 WSS 默认是 443 端口,大多数网站用的就是 80 和 443 端口。


1.2 SSL

SSL(Secure Socket Layer,安全套接层) 简单来说是一种加密技术, 通过它, 我们可以在通信的双方上建立一个安全的通信链路, 因此数据交互的双方可以安全地通信, 而不需要担心数据被窃取. 关于 SSL 的深入知识, 可以看这篇文章: SSL/TLS协议运行机制的概述。

1.3 WSS

WSS 是 Web Socket Secure 的简称, 它是 WebSocket 的加密版本. 我们知道 WebSocket 中的数据是不加密的, 但是不加密的数据很容易被别有用心的人窃取, 因此为了保护数据安全, 人们将 WebSocket 与 SSL 结合, 实现了安全的 WebSocket 通信, 即 WebSocket Secure。所以说 WSS 是使用 SSL 进行加密了的 WebSocket 通信技术。

1.3 HTTPS

其实 HTTPS 和 WSS 类似, HTTP 之于 HTTPS 就像 WebSocket 之于 WebSocket Secure。 HTTP 协议本身也是明文传输, 因此为了数据的安全性, 人们利用 SSL 作为加密通道, 在 SSL 之上传递 HTTP 数据, 因此 SSL 加密通道上运行的 HTTP 协议就被称为 HTTPS 了。

1.4 总结

SSL 是基础, 在 SSL 上运行 WebSocket 协议就是 WSS; 在 SSL 上运行 HTTP 协议就是 HTTPS。

2. SSL单向/双向认证

2.1 单向认证 SSL 协议的具体过程

  1. 客户端的浏览器向服务器传送客户端 SSL 协议的版本号,加密算法的种类,产生的随机数,以及其他服务器和客户端之间通讯所需要的各种信息。
  2. 服务器向客户端传送 SSL 协议的版本号,加密算法的种类,随机数以及其他相关信息,同时服务器还将向客户端传送自己的证书。
  3. 客户利用服务器传过来的信息验证服务器的合法性,服务器的合法性包括:证书是否过期,发行服务器证书的 CA 是否可靠,发行者证书的公钥能否正确解开服务器证书的“发行者的数字签名”,服务器证书上的域名是否和服务器的实际域名相匹配。如果合法性验证没有通过, 通讯将断开;如果合法性验证通过,将继续进行第四步。
  4. 用户端随机产生一个用于后面通讯的“对称密码”,然后用服务器的公钥(服务器的公钥从步骤②中的服务器的证书中获得)对其加密,然后将加密后的“预主密码”传给服务器。
  5. 如果服务器要求客户的身份认证(在握手过程中为可选),用户可以建立一个随机数然后对其进行数据签名,将这个含有签名的随机数和客户自己的证书以及加密过的“预主密码”一起传给服务器。
  6. 如果服务器要求客户的身份认证,服务器必须检验客户证书和签名随机数的合法性,具体的合法性验证过程包括:客户的证书使用日期是否有效,为客户提供证书的 CA 是否可靠,发行CA 的公钥能否正确解开客户证书的发行 CA 的数字签名,检查客户的证书是否在证书废止列表(CRL)中。检验如果没有通过,通讯立刻中断;如果验证通过,服务器将用自己的私钥解开加密的“预主密码 ”,然后执行一系列步骤来产生主通讯密码(客户端也将通过同样的方法产生相同的主通讯密码)。
  7. 服务器和客户端用相同的主密码即“通话密码”,一个对称密钥用于 SSL 协议的安全数据通讯的加解密通讯。同时在 SSL 通讯过程中还要完成数据通讯的完整性,防止数据通讯中的任何变化。
  8. 客户端向服务器端发出信息,指明后面的数据通讯将使用的步骤⑦中的主密码为对称密钥,同时通知服务器客户端的握手过程结束。
  9. 服务器向客户端发出信息,指明后面的数据通讯将使用的步骤⑦中的主密码为对称密钥,同时通知客户端服务器端的握手过程结束。
  10. SSL 的握手部分结束,SSL 安全通道的数据通讯开始,客户和服务器开始使用相同的对称密钥进行数据通讯,同时进行通讯完整性的检验。

2.2 双向认证 SSL 协议的具体过程

  1. 浏览器发送一个连接请求给安全服务器。
  2. 服务器将自己的证书,以及同证书相关的信息发送给客户浏览器。
  3. 客户浏览器检查服务器送过来的证书是否是由自己信赖的 CA 中心所签发的。如果是,就继续执行协议;如果不是,客户浏览器就给客户一个警告消息:警告客户这个证书不是可以信赖的,询问客户是否需要继续。
  4. 接着客户浏览器比较证书里的消息,例如域名和公钥,与服务器刚刚发送的相关消息是否一致,如果是一致的,客户浏览器认可这个服务器的合法身份。
  5. 服务器要求客户发送客户自己的证书。收到后,服务器验证客户的证书,如果没有通过验证,拒绝连接;如果通过验证,服务器获得用户的公钥。
  6. 客户浏览器告诉服务器自己所能够支持的通讯对称密码方案。
  7. 服务器从客户发送过来的密码方案中,选择一种加密程度最高的密码方案,用客户的公钥加过密后通知浏览器。
  8. 浏览器针对这个密码方案,选择一个通话密钥,接着用服务器的公钥加过密后发送给服务器。
  9. 服务器接收到浏览器送过来的消息,用自己的私钥解密,获得通话密钥。
  10. 服务器、浏览器接下来的通讯都是用对称密码方案,对称密钥是加过密的。

上面所述的是双向认证 SSL 协议的具体通讯过程,这种情况要求服务器和用户双方都有证书。 单向认证 SSL 协议不需要客户拥有 CA 证书,具体的过程相对于上面的步骤,只需将服务器端验证客户证书的过程去掉,以及在协商对称密码方案,对称通话密钥时,服务器发送给客户的是没有加过密的 (这并不影响 SSL 过程的安全性)密码方案。这样,双方具体的通讯内容,就是加过密的数据,如果有第三方攻击,获得的只是加密的数据,第三方要获得有用的信息,就需要对加密 的数据进行解密,这时候的安全就依赖于密码方案的安全。而幸运的是,目前所用的密码方案,只要通讯密钥长度足够的长,就足够的安全。这也是我们强调要求使 用 128 位加密通讯的原因。

3. 证书格式说明

在使用openssl自己生成证书的时候,会发现网上很多例子生成的证书格式都不同,同一篇文章里也会有很多种格式. 所以就需要了解下 不同格式有什么区别和联系

参考博客http://blog.csdn.net/justinjing0612/article/details/7770301

参考博客http://www.cnblogs.com/lzjsky/archive/2010/11/14/1877143.html

  • der,cer文件一般是二进制格式的,只放证书,不含私钥
  • crt文件可能是二进制的,也可能是文本格式的,应该以文本格式居多,功能同der/cer
  • pem文件一般是文本格式的,可以放证书或者私钥,或者两者都有
  • pem如果只含私钥的话,一般用.key扩展名,而且可以有密码保护
  • pfx,p12文件是二进制格式,同时含私钥和证书,通常有保护密码

4. 使用openssl生成证书

因为我的系统是Mac,这里记录的是Mac申请自签名的SSL证书,其他系统也类似,这里不再赘述。

  1. 桌面创建"SSL"文件夹,用来存放申请证书过程中的所有文件。

  2. 打开"终端"并进入到"桌面->SSL"。

  3. 管理员权限(命令:sudo su)。

这个命令超级重要!重要!重要!没有在管理员权限下执行下面的操作,即使你可以完成前面几步,也会在最后一步卡住报错!

sudo su
  1. 创建rootCA.key(命令:openssl genrsa -des3 -out rootCA.key 2048)。

创建时需要输入一个密码,这个密码要记住,下一步有用。

openssl genrsa -des3 -out rootCA.key 2048

  1. 使用rootCA.key创建rootCA.pem(命令:openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 3650 -out rootCA.pem)

创建时需要输入rootCA.key的密码。 其他信息可以随意填写。

openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 3650 -out rootCA.pem

  1. 双击rootCA.pem证书。在钥匙串中双击,并修改为"始终信任"该证书

  1. 创建v3.ext文件(命令:touch v3.ext)
touch v3.ext

8、编辑v3.ext文件(命令:sudo vim v3.ext)

sudo vim v3.ext

将下列文字复制粘贴进去 注意最后一行,(DNS.1 = xxxxxxx) 这一行可以输入域名或IP。

authorityKeyIdentifier=keyid,issuerbasicConstraints=CA:FALSEkeyUsage=digitalSignature, nonRepudiation, keyEncipherment, dataEnciphermentsubjectAltName=@alt_names[alt_names]DNS.1 = 192.168.0.3

  1. 创建server.csr和server.key(命令:openssl req -new -sha256 -nodes -out server.csr -newkey rsa:2048 -keyout server.key)

这里要注意倒数第二项,必须填自己的IP地址或域名,如果IP为动态获取的,建议先改成固定IP。

openssl req -new -sha256 -nodes -out server.csr -newkey rsa:2048 -keyout server.key

  1. 创建server.crt(命令:openssl x509 -req -in server.csr -CA [rootCA.pem路径] -CAkey [rootCA.key路径] -CAcreateserial -out server.crt -days 500 -sha256 -extfile v3.ext)

去掉中括号,把对应文件路径写进去。 如果你报了“Error opening CA Certificate”这个错误,请先检查路径是否正确,如果正确请检查是否执行了第三步,我就卡在这卡了一晚上~ 如果一切正常会让你输入密码,输入完成后就会生成server.crt!!

openssl x509 -req -in server.csr -CA [rootCA.pem路径] -CAkey [rootCA.key路径] -CAcreateserial -out server.crt -days 500 -sha256 -extfile v3.ext

  1. 最后查看SSL文件夹

5. Nginx配置 WSS

修改 nginx.conf配置文件

map $http_upgrade $connection_upgrade {      default upgrade;      '' close;  }  upstream websocket {      server 192.168.0.3:8888;  }  server {      listen 8888;      server_name test.com;    ssl on;    ssl_certificate /usr/local/etc/nginx/ZC_chain.crt;    ssl_certificate_key /usr/local/etc/nginx/ZC_key.key;       #ssl_client_certificate /usr/local/etc/nginx/ZC_chain.crt;    ssl_session_timeout 20m;    ssl_verify_client off;    location / {          proxy_pass http://websocket;          proxy_http_version 1.1;          proxy_set_header Upgrade $http_upgrade;          proxy_set_header Connection "Upgrade";      }  }

128.190.0.3:8888是真正的服务端地址,nginx所在域名是test.com,代理的端口号是8888,所以前端访问的时候这样配置:

WEBSOCKET_URL: 'wss://test.com:8888',

检查nginx.conf正确性:

nginx -t

重新加载配置文件:

nginx -s reload

6. WebSocketServer(基于SpringBoot)

基于SpringBoot整合WebSocket实现前后端互推消息,该代码可以用于ws协议以及wss协议进行测试。

  1. 首先创建一个springboot项目,网上教程很多,很简单,最终的目录结构如下:

  1. 项目的pom.xml如下:
<?xml version="1.0" encoding="UTF-8"?><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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0modelVersion><parent><groupId>org.springframework.bootgroupId><artifactId>spring-boot-starter-parentartifactId><version>2.3.3.RELEASEversion><relativePath/> parent><groupId>com.examplegroupId><artifactId>webSocketartifactId><version>0.0.1-SNAPSHOTversion><name>webSocketname><description>Demo project for Spring Bootdescription>

<properties><java.version>1.8java.version>properties>

<dependencies><dependency><groupId>org.springframework.bootgroupId><artifactId>spring-boot-starter-websocketartifactId>dependency>

<dependency><groupId>org.springframework.bootgroupId><artifactId>spring-boot-starter-testartifactId><scope>testscope><exclusions><exclusion><groupId>org.junit.vintagegroupId><artifactId>junit-vintage-engineartifactId>exclusion>exclusions>dependency><dependency><groupId>org.projectlombokgroupId><artifactId>lombokartifactId><version>1.18.10version>dependency>dependencies>

<build><plugins><plugin><groupId>org.springframework.bootgroupId><artifactId>spring-boot-maven-pluginartifactId>plugin>plugins>build>

project>

  1. application.properties中配置端口号。
server.port=8888
  1. 配置类
import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configurationpublic class WebSocketConfig {/**     * ServerEndpointExporter 作用     *     * 这个Bean会自动注册使用@ServerEndpoint注解声明的websocket endpoint     *     * @return     */@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();    }}
  1. 核心类
import org.springframework.stereotype.Component;

import javax.websocket.*;import javax.websocket.server.PathParam;import javax.websocket.server.ServerEndpoint;import java.io.IOException;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.atomic.AtomicInteger;

@ServerEndpoint("/webSocket/{sid}")@Componentpublic class WebSocketServer {//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。private static AtomicInteger onlineNum = new AtomicInteger();

//concurrent包的线程安全Set,用来存放每个客户端对应的WebSocketServer对象。private static ConcurrentHashMap sessionPools = new ConcurrentHashMap<>();//发送消息public void sendMessage(Session session, String message) throws IOException {if(session != null){synchronized (session) {//                System.out.println("发送数据:" + message);                session.getBasicRemote().sendText(message);            }        }    }//给指定用户发送信息public void sendInfo(String userName, String message){        Session session = sessionPools.get(userName);try {            sendMessage(session, message);        }catch (Exception e){            e.printStackTrace();        }    }//建立连接成功调用@OnOpenpublic void onOpen(Session session, @PathParam(value = "sid") String userName){        sessionPools.put(userName, session);        addOnlineCount();        System.out.println(userName + "加入webSocket!当前人数为" + onlineNum);try {            sendMessage(session, "欢迎" + userName + "加入连接!");        } catch (IOException e) {            e.printStackTrace();        }    }//关闭连接时调用@OnClosepublic void onClose(@PathParam(value = "sid") String userName){        sessionPools.remove(userName);        subOnlineCount();        System.out.println(userName + "断开webSocket连接!当前人数为" + onlineNum);    }//收到客户端信息@OnMessagepublic void onMessage(String message) throws IOException{        message = "客户端:" + message + ",已收到";        System.out.println(message);for (Session session: sessionPools.values()) {try {                sendMessage(session, message);            } catch(Exception e){                e.printStackTrace();continue;            }        }    }//错误时调用@OnErrorpublic void onError(Session session, Throwable throwable){        System.out.println("发生错误");        throwable.printStackTrace();    }public static void addOnlineCount(){        onlineNum.incrementAndGet();    }public static void subOnlineCount() {        onlineNum.decrementAndGet();    }}
  1. 在Controller中跳转页面
package com.example.controller;

import com.example.service.WebSocketServer;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.servlet.ModelAndView;

@Controllerpublic class SocketController {

@Autowiredprivate WebSocketServer webSocketServer;

@RequestMapping("/index")public String index() {return "index";    }

@GetMapping("/webSocket")public ModelAndView socket() {        ModelAndView mav = new ModelAndView("/webSocket");//mav.addObject("userId", userId);return mav;    }

}
  1. 前端代码在webSocket.html中:
span style="line-height: 26px;">html><html lang="en"><head><meta charset="UTF-8"><title>WebSockettitle>

head><body><h3>hello socketh3><p>【userId】:<div><input id="userId" name="userId" type="text" value="10">div><p>【toUserId】:<div><input id="toUserId" name="toUserId" type="text" value="20">div><p>【toUserId】:<div><input id="contentText" name="contentText" type="text" value="hello websocket">div><p>操作:<div><a onclick="openSocket()">开启socketa>div><p>【操作】:<div><a onclick="sendMessage()">发送消息a>div>body><script>var socket;function openSocket() {if(typeof(WebSocket) == "undefined") {console.log("您的浏览器不支持WebSocket");        }else{console.log("您的浏览器支持WebSocket");//实现化WebSocket对象,指定要连接的服务器地址与端口  建立连接var userId = document.getElementById('userId').value;var socketUrl="wss://192.168.0.3:8888/webSocket/"+userId;console.log(socketUrl);if(socket!=null){                socket.close();                socket=null;            }            socket = new WebSocket(socketUrl);//打开事件            socket.onopen = function() {console.log("websocket已打开");//socket.send("这是来自客户端的消息" + location.href + new Date());            };//获得消息事件            socket.onmessage = function(msg) {var serverMsg = "收到服务端信息:" + msg.data;console.log(serverMsg);//发现消息进入    开始处理前端触发逻辑            };//关闭事件            socket.onclose = function() {console.log("websocket已关闭");            };//发生了错误事件            socket.onerror = function() {console.log("websocket发生了错误");            }        }    }function sendMessage() {if(typeof(WebSocket) == "undefined") {console.log("您的浏览器不支持WebSocket");        }else {// console.log("您的浏览器支持WebSocket");var toUserId = document.getElementById('toUserId').value;var contentText = document.getElementById('contentText').value;var msg = '{"toUserId":"'+toUserId+'","contentText":"'+contentText+'"}';console.log(msg);            socket.send(msg);        }    }script>html>

7. WSS + WebSocketClient

  1. maven依赖

备注:maven仓库官方(https://mvnrepository.com/)

<dependency><groupId>org.java-websocketgroupId><artifactId>Java-WebSocketartifactId><version>1.3.0version>dependency>

这个ws客户端对wss支持不好,源码中的wss client 还要使用证书。可以修改为不验证证书,具体看工具类代码。

  1. 工具类
package com.example.wss;import java.net.URI;import java.security.cert.CertificateException;import java.security.cert.X509Certificate;import java.util.Map;

import javax.net.ssl.HostnameVerifier;import javax.net.ssl.SSLContext;import javax.net.ssl.SSLSession;import javax.net.ssl.TrustManager;import javax.net.ssl.X509TrustManager;

import org.java_websocket.client.DefaultSSLWebSocketClientFactory;import org.java_websocket.client.WebSocketClient;import org.java_websocket.drafts.Draft;/** * 


* WSS工具类
*


*
* @author: hejianhui
* @create: 2020-08-23 00:27
* @see MyWssUtil
* @since JDK1.8
*/
abstract class MyWssUtil extends WebSocketClient {

public MyWssUtil(URI serverURI) {
super(serverURI);
if (serverURI.toString().contains("wss://"))
trustAllHosts(this);
}

public MyWssUtil(URI serverURI, Draft draft) {
super(serverURI, draft);
if (serverURI.toString().contains("wss://"))
trustAllHosts(this);
}

public MyWssUtil(URI serverURI, Draft draft, Map headers, int connecttimeout) {
super(serverURI, draft, headers, connecttimeout);
if (serverURI.toString().contains("wss://"))
trustAllHosts(this);
}

final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};

static void trustAllHosts(MyWssUtil appClient) {
System.out.println("start...");
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[]{};
}

@Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
// TODO Auto-generated method stub

}

@Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
// TODO Auto-generated method stub

}
}};

try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
appClient.setWebSocketFactory(new DefaultSSLWebSocketClientFactory(sc));
} catch (Exception e) {
e.printStackTrace();
}
}
}

  1. 使用工具进行wss协议的接口请求
package com.example.wss;

import org.java_websocket.WebSocket;import org.java_websocket.drafts.Draft;import org.java_websocket.drafts.Draft_17;import org.java_websocket.handshake.ServerHandshake;

import java.net.URI;import java.net.URISyntaxException;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;

/** * 


* 进行wss协议的接口请求测试
*


*
* @author: hejianhui
* @create: 2020-08-23 00:30
* @see WssTest
* @since JDK1.8
*/
public class WssTest {
public static List result = new ArrayList<>();public static String initmsg = "{'lat':'118.817891','lng':'31.931724','speed':'0','distance':'0'}";public static void main(String[] args) throws URISyntaxException {
Map headers = new HashMap<>();// 根据服务端具体进行配置// headers.put("Sec-WebSocket-Extensions", "permessage-deflate; client_max_window_bits");// headers.put("Sec-WebSocket-Key", "");// headers.put("Sec-WebSocket-Protocol", "x-access-token, ");// headers.put("Sec-WebSocket-Version", "13");// 以下请求头可以不用传// headers.put("Connection", "Upgrade");// headers.put("Upgrade", "websocket");// headers.put("Accept-Encoding", "gzip, deflate, br");// headers.put("Accept-Language", "zh-CN,zh;q=0.9");// headers.put("Cache-Control", "no-cache");// headers.put("Host", "test.com");// headers.put("Origin", "https://test.com");// headers.put("Pragma", "no-cache");// headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36");
Draft draft = new Draft_17();
draft.setParseMode(WebSocket.Role.CLIENT);new MyWssUtil(new URI("wss://****************填写自己的url******************")
, draft
, headers
, 10
) {@Overridepublic void onClose(int arg0, String arg1, boolean arg2) {
System.out.println(String.format("onClose:【%s】【%s】【%s】", arg0, arg1, arg2));
}@Overridepublic void onError(Exception arg0) {
System.out.println(String.format("onError:%s", arg0));
}@Overridepublic void onMessage(String arg0) {if (!arg0.equals("pong")) {
result.add(arg0);
System.out.println(String.format("onMessage:%s", arg0));
}this.send(arg0);
}@Overridepublic void onOpen(ServerHandshake arg0) {
System.out.println(String.format("onOpen:%s", arg0));this.send(initmsg);
}
}.connect();
}
}

完整代码地址:https://github.com/org-hejianhui/websocket


部分图片来源于网络,版权归原作者,侵删。

?点击阅读原文,查看往期内容!

                              快留言?和我互动吧~

nginx websocket wss 连接失败 failed_Nginx 配置WSS 解析与实战相关推荐

  1. 瑞星升级提示网络连接失败网络配置后重试12007

    瑞星升级提示网络连接失败网络配置后重试12007 安装瑞星2009升级提示网络连接失败请正确设置网络配置后重试12007 文:weh  发表时间:2009-3-9 14:33:14 Windows20 ...

  2. nginx websocket wss 连接失败 failed_浅谈WebSocket协议、WS协议和WSS协议原理及关系

    现如今,一些游戏,网站,APP,支付行业的网络经常会收到DDOS和CC,因此这个事情也变得不足为奇了.但在防护方案中有多种不同的方案.如,今天有几个同事在针对高防CDN问题讨论的时,谈到WebSock ...

  3. 瑞星升级提示网络连接失败网络配置后重试(12007) 解决办法

    安装瑞星2009升级提示网络连接失败请正确设置网络配置后重试12007 Windows2003 server安装瑞星2009升级提示网络连接失败请正确设置网络配置后重试12007,瑞星网站也不能上,以 ...

  4. BLE错误码全面解析连接失败原因错误码解析BLE Disconnect Reason

    错误代码用于指示错误的原因,当出现一些异常情况时会出现一些对应的错误码.错误代码的大小为8个字节. 未知HCI命令(0x01) 未知HCI命令错误代码表示控制器不理解主机发送的HCI命令数据包操作码. ...

  5. Xftp连接到Linux服务器时提示连接失败的配置

    场景 使用Xftp连接到CentOS系统时提示 会话的属性设置为 这里的协议应该是SFTP,并且默认端口是22就可以建立连接了

  6. apache配置wss

    ws和wss的区别与http和https相似. ws是没有证书安全的websocket,wss是有ssl证书安全的websocket 在apache环境下配置wss步骤: 1.需要在httpd.con ...

  7. php reactphp wss_swoole 使用websocket建立wss连接

    wss协议实际是websocket+SSL,就是在websocket协议上加入SSL层,类似https(http+SSL).  ws一般默认是80端口,而wss默认是443端口,大多数网站用的就是80 ...

  8. nginx配置wss协议

    需求:nginx配置websocket协议连接,(背景,在一个使用一个免费的仅仅支持单域名的证书时,既要支持https协议,也要支持wss协议时,我们可以配置一个nginx根据不同的路径去跳转) 我所 ...

  9. ThinkPHP5.0的think-swoole 开启WebSocket的SSL支持 使用wss连接

    相关文章:ThinkPHP5.0结合Swoole开发WebSocket在线聊天 Swoole WebSocket开启SSL支持 使用wss连接 找到think-swoole的Server.php: 在 ...

最新文章

  1. 如何解决ORA-04031错误
  2. Summer Training day4上帝与集合的正确用法 欧拉函数+降幂公式
  3. 【论文研读】【医学图像分割】【BCRNN】Fine-grained Recurrent Neural Networks for Automatic Prostate Segmentation ...
  4. jfianl中 解决jetty Form too large
  5. c语言中return,和exit的区别
  6. SEO行业应该如何给客户报价
  7. 一种数字全息自动聚焦技术研究及实例分析
  8. 『信息安全技术』 标准系列合集(467个)
  9. 11月赠书活动获奖读者
  10. 照片放大工具Topaz Gigapixel AI for Mac
  11. puber們這一季的愛情啊
  12. WIN10 时间同步
  13. 基尼系数,省级层面、地级市层面、Dagum1997方法,整理好的面板数据
  14. mysql导入excel
  15. 2020放弃安卓用鸿蒙,放弃鸿蒙用安卓,认输就在一念之间,网友13亿人养不起华为...
  16. 给中国学生的第三封信——成功、自信、快乐
  17. android端蓝牙控制单片机,android 蓝牙控制继电器——单片机控制端
  18. C++智能指针详解(auto_ptr、unique_ptr、shared_ptr)
  19. 转贴:人活着到底为了啥?
  20. GREoverIPsec的本质华为

热门文章

  1. 201712-2-游戏
  2. Maxwell数据库数据采集-大数据week12-DAY1-Maxwell
  3. 《ActionScript 3.0基础教程》——2.2 显示队列概述
  4. django chart mysql,docker Django+mysql+ECharts+AngularJS简单搭建数据可视化
  5. java jmx 监控tomcat_jmx监控之Tomcat
  6. 使用truss、strace或ltrace诊断软件的疑难杂症
  7. 数字后端基本概念介绍<Tap Cell>
  8. AIX errpt 命令输出说明
  9. idea开发vue项目时,使用@引入组件警告:Module is not installed
  10. 2019-07-22