nginx websocket wss 连接失败 failed_Nginx 配置WSS 解析与实战
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 协议的具体过程
- 客户端的浏览器向服务器传送客户端 SSL 协议的版本号,加密算法的种类,产生的随机数,以及其他服务器和客户端之间通讯所需要的各种信息。
- 服务器向客户端传送 SSL 协议的版本号,加密算法的种类,随机数以及其他相关信息,同时服务器还将向客户端传送自己的证书。
- 客户利用服务器传过来的信息验证服务器的合法性,服务器的合法性包括:证书是否过期,发行服务器证书的 CA 是否可靠,发行者证书的公钥能否正确解开服务器证书的“发行者的数字签名”,服务器证书上的域名是否和服务器的实际域名相匹配。如果合法性验证没有通过, 通讯将断开;如果合法性验证通过,将继续进行第四步。
- 用户端随机产生一个用于后面通讯的“对称密码”,然后用服务器的公钥(服务器的公钥从步骤②中的服务器的证书中获得)对其加密,然后将加密后的“预主密码”传给服务器。
- 如果服务器要求客户的身份认证(在握手过程中为可选),用户可以建立一个随机数然后对其进行数据签名,将这个含有签名的随机数和客户自己的证书以及加密过的“预主密码”一起传给服务器。
- 如果服务器要求客户的身份认证,服务器必须检验客户证书和签名随机数的合法性,具体的合法性验证过程包括:客户的证书使用日期是否有效,为客户提供证书的 CA 是否可靠,发行CA 的公钥能否正确解开客户证书的发行 CA 的数字签名,检查客户的证书是否在证书废止列表(CRL)中。检验如果没有通过,通讯立刻中断;如果验证通过,服务器将用自己的私钥解开加密的“预主密码 ”,然后执行一系列步骤来产生主通讯密码(客户端也将通过同样的方法产生相同的主通讯密码)。
- 服务器和客户端用相同的主密码即“通话密码”,一个对称密钥用于 SSL 协议的安全数据通讯的加解密通讯。同时在 SSL 通讯过程中还要完成数据通讯的完整性,防止数据通讯中的任何变化。
- 客户端向服务器端发出信息,指明后面的数据通讯将使用的步骤⑦中的主密码为对称密钥,同时通知服务器客户端的握手过程结束。
- 服务器向客户端发出信息,指明后面的数据通讯将使用的步骤⑦中的主密码为对称密钥,同时通知客户端服务器端的握手过程结束。
- SSL 的握手部分结束,SSL 安全通道的数据通讯开始,客户和服务器开始使用相同的对称密钥进行数据通讯,同时进行通讯完整性的检验。
2.2 双向认证 SSL 协议的具体过程
- 浏览器发送一个连接请求给安全服务器。
- 服务器将自己的证书,以及同证书相关的信息发送给客户浏览器。
- 客户浏览器检查服务器送过来的证书是否是由自己信赖的 CA 中心所签发的。如果是,就继续执行协议;如果不是,客户浏览器就给客户一个警告消息:警告客户这个证书不是可以信赖的,询问客户是否需要继续。
- 接着客户浏览器比较证书里的消息,例如域名和公钥,与服务器刚刚发送的相关消息是否一致,如果是一致的,客户浏览器认可这个服务器的合法身份。
- 服务器要求客户发送客户自己的证书。收到后,服务器验证客户的证书,如果没有通过验证,拒绝连接;如果通过验证,服务器获得用户的公钥。
- 客户浏览器告诉服务器自己所能够支持的通讯对称密码方案。
- 服务器从客户发送过来的密码方案中,选择一种加密程度最高的密码方案,用客户的公钥加过密后通知浏览器。
- 浏览器针对这个密码方案,选择一个通话密钥,接着用服务器的公钥加过密后发送给服务器。
- 服务器接收到浏览器送过来的消息,用自己的私钥解密,获得通话密钥。
- 服务器、浏览器接下来的通讯都是用对称密码方案,对称密钥是加过密的。
上面所述的是双向认证 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证书,其他系统也类似,这里不再赘述。
桌面创建"SSL"文件夹,用来存放申请证书过程中的所有文件。
打开"终端"并进入到"桌面->SSL"。
管理员权限(命令:sudo su)。
这个命令超级重要!重要!重要!没有在管理员权限下执行下面的操作,即使你可以完成前面几步,也会在最后一步卡住报错!
sudo su
- 创建rootCA.key(命令:openssl genrsa -des3 -out rootCA.key 2048)。
创建时需要输入一个密码,这个密码要记住,下一步有用。
openssl genrsa -des3 -out rootCA.key 2048
- 使用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
- 双击rootCA.pem证书。在钥匙串中双击,并修改为"始终信任"该证书
- 创建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
- 创建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
- 创建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
- 最后查看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协议进行测试。
- 首先创建一个springboot项目,网上教程很多,很简单,最终的目录结构如下:
- 项目的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>
- application.properties中配置端口号。
server.port=8888
- 配置类
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(); }}
- 核心类
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(); }}
- 在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; }
}
- 前端代码在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
- maven依赖
备注:maven仓库官方(https://mvnrepository.com/)
<dependency><groupId>org.java-websocketgroupId><artifactId>Java-WebSocketartifactId><version>1.3.0version>dependency>
这个ws客户端对wss支持不好,源码中的wss client 还要使用证书。可以修改为不验证证书,具体看工具类代码。
- 工具类
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();
}
}
}
- 使用工具进行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 解析与实战相关推荐
- 瑞星升级提示网络连接失败网络配置后重试12007
瑞星升级提示网络连接失败网络配置后重试12007 安装瑞星2009升级提示网络连接失败请正确设置网络配置后重试12007 文:weh 发表时间:2009-3-9 14:33:14 Windows20 ...
- nginx websocket wss 连接失败 failed_浅谈WebSocket协议、WS协议和WSS协议原理及关系
现如今,一些游戏,网站,APP,支付行业的网络经常会收到DDOS和CC,因此这个事情也变得不足为奇了.但在防护方案中有多种不同的方案.如,今天有几个同事在针对高防CDN问题讨论的时,谈到WebSock ...
- 瑞星升级提示网络连接失败网络配置后重试(12007) 解决办法
安装瑞星2009升级提示网络连接失败请正确设置网络配置后重试12007 Windows2003 server安装瑞星2009升级提示网络连接失败请正确设置网络配置后重试12007,瑞星网站也不能上,以 ...
- BLE错误码全面解析连接失败原因错误码解析BLE Disconnect Reason
错误代码用于指示错误的原因,当出现一些异常情况时会出现一些对应的错误码.错误代码的大小为8个字节. 未知HCI命令(0x01) 未知HCI命令错误代码表示控制器不理解主机发送的HCI命令数据包操作码. ...
- Xftp连接到Linux服务器时提示连接失败的配置
场景 使用Xftp连接到CentOS系统时提示 会话的属性设置为 这里的协议应该是SFTP,并且默认端口是22就可以建立连接了
- apache配置wss
ws和wss的区别与http和https相似. ws是没有证书安全的websocket,wss是有ssl证书安全的websocket 在apache环境下配置wss步骤: 1.需要在httpd.con ...
- php reactphp wss_swoole 使用websocket建立wss连接
wss协议实际是websocket+SSL,就是在websocket协议上加入SSL层,类似https(http+SSL). ws一般默认是80端口,而wss默认是443端口,大多数网站用的就是80 ...
- nginx配置wss协议
需求:nginx配置websocket协议连接,(背景,在一个使用一个免费的仅仅支持单域名的证书时,既要支持https协议,也要支持wss协议时,我们可以配置一个nginx根据不同的路径去跳转) 我所 ...
- ThinkPHP5.0的think-swoole 开启WebSocket的SSL支持 使用wss连接
相关文章:ThinkPHP5.0结合Swoole开发WebSocket在线聊天 Swoole WebSocket开启SSL支持 使用wss连接 找到think-swoole的Server.php: 在 ...
最新文章
- 如何解决ORA-04031错误
- Summer Training day4上帝与集合的正确用法 欧拉函数+降幂公式
- 【论文研读】【医学图像分割】【BCRNN】Fine-grained Recurrent Neural Networks for Automatic Prostate Segmentation ...
- jfianl中 解决jetty Form too large
- c语言中return,和exit的区别
- SEO行业应该如何给客户报价
- 一种数字全息自动聚焦技术研究及实例分析
- 『信息安全技术』 标准系列合集(467个)
- 11月赠书活动获奖读者
- 照片放大工具Topaz Gigapixel AI for Mac
- puber們這一季的愛情啊
- WIN10 时间同步
- 基尼系数,省级层面、地级市层面、Dagum1997方法,整理好的面板数据
- mysql导入excel
- 2020放弃安卓用鸿蒙,放弃鸿蒙用安卓,认输就在一念之间,网友13亿人养不起华为...
- 给中国学生的第三封信——成功、自信、快乐
- android端蓝牙控制单片机,android 蓝牙控制继电器——单片机控制端
- C++智能指针详解(auto_ptr、unique_ptr、shared_ptr)
- 转贴:人活着到底为了啥?
- GREoverIPsec的本质华为
热门文章
- 201712-2-游戏
- Maxwell数据库数据采集-大数据week12-DAY1-Maxwell
- 《ActionScript 3.0基础教程》——2.2 显示队列概述
- django chart mysql,docker Django+mysql+ECharts+AngularJS简单搭建数据可视化
- java jmx 监控tomcat_jmx监控之Tomcat
- 使用truss、strace或ltrace诊断软件的疑难杂症
- 数字后端基本概念介绍<Tap Cell>
- AIX errpt 命令输出说明
- idea开发vue项目时,使用@引入组件警告:Module is not installed
- 2019-07-22