RFC6455-The WebSocket protocol 之五:Opening Handshake 4.2-4.4

2024-09-02 05:18

本文主要是介绍RFC6455-The WebSocket protocol 之五:Opening Handshake 4.2-4.4,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

参考:http://jinnianshilongnian.iteye.com/blog/1898350

4.2 Server-Side Requirements
服务器端的要求
Servers MAY offload the management of the connection to other agents
   on the network, for example, load balancers and reverse proxies.  In
   such a situation, the server for the purposes of this specification
   is considered to include all parts of the server-side infrastructure
   from the first device to terminate the TCP connection all the way to
   the server that processes requests and sends responses.
服务器可能会把连接的管理托管给网络上的其它代理,比如负载均衡器和反向代理。在这种情况下,本文中提到的服务器包含服务端所有的基础设施,包括服务器处理请求和响应一直到连接关闭过程中所涉及到的所有设备。

   EXAMPLE: A data center might have a server that responds to WebSocket
   requests with an appropriate handshake and then passes the connection
   to another server to actually process the data frames.  For the
   purposes of this specification, the "server" is the combination of
   both computers.
例如,数据中心的一台服务器使用正确的握手对WebSocket请求进行了响应,然后把这个连接传递给另外一台服务器,这台服务器真正处理数据。按照本说明书的定义,“server”指的是这两台服务器。

4.2.1.  Reading the Client’s Opening Handshake
读取客户端的握手
   When a client starts a WebSocket connection, it sends its part of the
   opening handshake.  The server must parse at least part of this
   handshake in order to obtain the necessary information to generate
   the server part of the handshake.
当一个客户端建立了WebSocket连接后,它发送握手的部分信息。服务器必须能解析本握手的最小部分的数据,从而可以获得足够的信息来生成server端的握手。

   The client’s opening handshake consists of the following parts.  If
   the server, while reading the handshake, finds that the client did
   not send a handshake that matches the description below (note that as
   per [RFC2616], the order of the header fields is not important),
   including but not limited to any violations of the ABNF grammar
   specified for the components of the handshake, the server MUST stop
   processing the client’s handshake and return an HTTP response with an
   appropriate error code (such as 400 Bad Request).
客户端的握手由以下部分组成。当server在读取握手信息时,如果发现客户端发送了一个与以下描述不匹配的握手(注意,头信息的顺序不重要),包括但不仅限于违反了ABNF语法中对握手组件的定义,服务器必须马上停止处理该握手并发送一个合适的http错误代码(例如400代表错误请求)。

   1.   An HTTP/1.1 or higher GET request, including a "Request-URI"
        [RFC2616] that should be interpreted as a /resource name/
        defined in Section 3 (or an absolute HTTP/HTTPS URI containing
        the /resource name/).
1.1及以上版本的包含 "Request-URI"的http get请求,应该被解析成第三种中定义的resource name的格式(或者一个包含resource name的绝对Http/https URI)。

   2.   A |Host| header field containing the server’s authority.
Host头字段包含了服务器的权限。

   3.   An |Upgrade| header field containing the value "websocket",
        treated as an ASCII case-insensitive value.
包含"websocket"值的Upgrade头字段,需要按照大小写不敏感的ASCII码处理。

   4.   A |Connection| header field that includes the token "Upgrade",
        treated as an ASCII case-insensitive value.
包含"Upgrade"值的Connection头字段,需要按照大小写不敏感的ASCII码处理。

   5.   A |Sec-WebSocket-Key| header field with a base64-encoded (see
        Section 4 of [RFC4648]) value that, when decoded, is 16 bytes in
        length.
含有base64编码数据的Sec-WebSocket-Key头字段,解码后的长度是16位。

   6.   A |Sec-WebSocket-Version| header field, with a value of 13.
Sec-WebSocket-Version头字段的值为13.

   7.   Optionally, an |Origin| header field.  This header field is sent
        by all browser clients.  A connection attempt lacking this
        header field SHOULD NOT be interpreted as coming from a browser
        client.
Origin头字段是可选的。这个字段由浏览器类型的客户端发送。缺少该头字段的连接,应该被认为不是来自浏览器客户端。

   8.   Optionally, a |Sec-WebSocket-Protocol| header field, with a list
        of values indicating which protocols the client would like to
        speak, ordered by preference.
Sec-WebSocket-Protocol 头字段是可选的,其值是客户端计划使用的协议的列表,按照优先级排序。

   9.   Optionally, a |Sec-WebSocket-Extensions| header field, with a
        list of values indicating which extensions the client would like
        to speak.  The interpretation of this header field is discussed
        in Section 9.1.
Sec-WebSocket-Extensions头字段是可选的,其值是客户端计划采用的扩展列表。该字段的解析在9.1中讨论。

10.  Optionally, other header fields, such as those used to send
        cookies or request authentication to a server.  Unknown header
        fields are ignored, as per [RFC2616].
其它字段是可选的,如发送cookies或请求认证等。依照RFC2616不认识的头字段将被忽略。

4.2.2. Sending the Server’s Opening Handshake
发送server端的握手。

When a client establishes a WebSocket connection to a server, the
server MUST complete the following steps to accept the connection and
send the server’s opening handshake.
当一个客户端与服务器建立了WebSocket连接后,服务器必须完成以下的步骤,从而接收客户端请求并发送服务端的握手。

1. If the connection is happening on an HTTPS (HTTP-over-TLS) port,
perform a TLS handshake over the connection. If this fails
(e.g., the client indicated a host name in the extended client
hello "server_name" extension that the server does not host),
then close the connection; otherwise, all further communication
for the connection (including the server’s handshake) MUST run
through the encrypted tunnel [RFC5246].
假如连接建立在https端口之上,在连接上执行了TLS握手。假如失败(例如客户端指明的主机名在服务端不存在),则关闭连接;否则该接口上所有的进一步的交互(包括服务端的握手)必须通过加密的通道。
2. The server can perform additional client authentication, for
example, by returning a 401 status code with the corresponding
|WWW-Authenticate| header field as described in [RFC2616].
服务端可以对客户端进行额外的校验,例如,可以返回401状态码与在RFC2616中描述的WWW-Authenticate的头字段。

3. The server MAY redirect the client using a 3xx status code
[RFC2616]. Note that this step can happen together with, before,
or after the optional authentication step described above.
服务端可以通过3XX状态码对客户端进行重定向。注意,该步骤可以同上述所说的验证阶段同时、提前或滞后执行。

4. Establish the following information:
构建下述信息:

/origin/
The |Origin| header field in the client’s handshake indicates
the origin of the script establishing the connection. The
origin is serialized to ASCII and converted to lowercase. The
server MAY use this information as part of a determination of
whether to accept the incoming connection. If the server does
not validate the origin, it will accept connections from
anywhere. If the server does not wish to accept this
connection, it MUST return an appropriate HTTP error code
(e.g., 403 Forbidden) and abort the WebSocket handshake
described in this section. For more detail, refer to
Section 10.
客户端握手中的Origin头字段代表的是建立连接的脚本的“源”。“源”被序列化成ASCII码并转成小写的。服务端可能会把该元素作为考虑是否接收接入连接的一个因素。假如服务端不验证Origin,它可以从任何地方接收连接。假如服务端不期望接收该连接,它必须返回一个适当的HTTP错误码(例如:403拒绝)然后终止本节中描述的WebSocket握手。在第十章中会有更多信息。

/key/
The |Sec-WebSocket-Key| header field in the client’s handshake
includes a base64-encoded value that, if decoded, is 16 bytes
in length. This (encoded) value is used in the creation of
the server’s handshake to indicate an acceptance of the
connection. It is not necessary for the server to base64-
decode the |Sec-WebSocket-Key| value.
客户端握手中的Sec-WebSocket-Key头字段包含一个base64编码的值,解码后是16位长。创建服务端握手的时候会用到该编码后的值,代表着接受该连接。服务端不需要去解码这个值。

/version/
The |Sec-WebSocket-Version| header field in the client’s
handshake includes the version of the WebSocket Protocol with
which the client is attempting to communicate. If this
version does not match a version understood by the server, the
server MUST abort the WebSocket handshake described in this
section and instead send an appropriate HTTP error code (such
as 426 Upgrade Required) and a |Sec-WebSocket-Version| header
field indicating the version(s) the server is capable of
understanding.
客户端握手中的Sec-WebSocket-Version是客户端预计进行交互的WebSocket协议的版本。如果这个版本与服务端支持的版本不符,服务端必须终止这个Websocket握手,返回一个合适的http错误码(就像升级需要的426),并且把服务端支持的版本返回去。

/resource name/
An identifier for the service provided by the server. If the
server provides multiple services, then the value should be
derived from the resource name given in the client’s handshake
in the "Request-URI" [RFC2616] of the GET method. If the
requested service is not available, the server MUST send an
appropriate HTTP error code (such as 404 Not Found) and abort
the WebSocket handshake.
服务端提供的服务的标志。假如服务端提供了多种服务,这个值需要从客户端握手中的resource name推断出来。假如要求的服务不可用,服务端必须返回一个适当的错误码(例如404无法找到错误)并终止WebSocket握手。

/subprotocol/
Either a single value representing the subprotocol the server
is ready to use or null. The value chosen MUST be derived
from the client’s handshake, specifically by selecting one of
the values from the |Sec-WebSocket-Protocol| field that the
server is willing to use for this connection (if any). If the
client’s handshake did not contain such a header field or if
the server does not agree to any of the client’s requested
subprotocols, the only acceptable value is null. The absence
of such a field is equivalent to the null value (meaning that
if the server does not wish to agree to one of the suggested
subprotocols, it MUST NOT send back a |Sec-WebSocket-Protocol|
header field in its response). The empty string is not the
same as the null value for these purposes and is not a legal
value for this field. The ABNF for the value of this header
field is (token), where the definitions of constructs and
rules are as given in [RFC2616].
或者用一个值表明服务端准备使用的子协议,或者为null。选中的值必须从客户端的握手中推断出来,尤其是从服务端准备在该连接上使用的协议Sec-WebSocket-Protocol中选择一个。假如客户端握手中不包含该选项,或者服务端不接受客户端要求的任何子协议,唯一可以接受的值是null。没有这个选项等同于null(意思是如果服务端不打算认同任何一个推荐的子协议,那么在响应的时候必须不返回Sec-WebSocket-Protocol字段)。空字符串不等同于null而且也不是一个合法的取值。该头字段的ABNF值是(tocken),在[RFC2616中给出了构造定义和规则。


/extensions/
A (possibly empty) list representing the protocol-level
extensions the server is ready to use. If the server supports
multiple extensions, then the value MUST be derived from the
client’s handshake, specifically by selecting one or more of
the values from the |Sec-WebSocket-Extensions| field. The
absence of such a field is equivalent to the null value. The
empty string is not the same as the null value for these
purposes. Extensions not listed by the client MUST NOT be
listed. The method by which these values should be selected
and interpreted is discussed in Section 9.1.
该值标志服务端准备去使用的协议级别的扩展列表(可能为空)。假如服务端支持多个扩展,这个值必须从客户端的握手中推断出来,尤其是从Sec-WebSocket-Extensions字段中选择一个或多个值得时候。没有该字段等同于null。空字符串与null值不等价。客户端没有列出的扩展必须不被列出。如何选择及解读的方法在9.1节中会进行讨论。

5. If the server chooses to accept the incoming connection, it MUST
reply with a valid HTTP response indicating the following.
假如服务端决定接受接入的连接,它必须采用一个合法的HTTP response进行回应,该response包含以下信息:

1. A Status-Line with a 101 response code as per RFC 2616
[RFC2616]. Such a response could look like "HTTP/1.1 101
Switching Protocols".
按照RFC 2616描述的101响应编码行。 响应的格式如: "HTTP/1.1 101 Switching Protocols"。

2. An |Upgrade| header field with value "websocket" as per RFC
2616 [RFC2616].
按照RFC 2616描述的Upgrade 头字段,值是"websocket"。

3. A |Connection| header field with value "Upgrade".
Connection头字段,值是"Upgrade".

4. A |Sec-WebSocket-Accept| header field. The value of this
header field is constructed by concatenating /key/, defined
above in step 4 in Section 4.2.2, with the string "258EAFA5-
E914-47DA-95CA-C5AB0DC85B11", taking the SHA-1 hash of this
concatenated value to obtain a 20-byte value and base64-
encoding (see Section 4 of [RFC4648]) this 20-byte hash.
Sec-WebSocket-Accept头字段。连接4.2.2节第四步中定义的key与"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"串,对该串做SHA-1 散列加密后得到一个20位的串,再进行base64编码得到该字段的值。

The ABNF [RFC2616] of this header field is defined as follows:
这个头字段的ABNF定义如下:

Sec-WebSocket-Accept = base64-value-non-empty
base64-value-non-empty = (1*base64-data [ base64-padding ]) |
base64-padding
base64-data = 4base64-character
base64-padding = (2base64-character "==") |
(3base64-character "=")
base64-character = ALPHA | DIGIT | "+" | "/"

NOTE: As an example, if the value of the |Sec-WebSocket-Key| header
field in the client’s handshake were "dGhlIHNhbXBsZSBub25jZQ==", the
server would append the string "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
to form the string "dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-
C5AB0DC85B11". The server would then take the SHA-1 hash of this
string, giving the value 0xb3 0x7a 0x4f 0x2c 0xc0 0x62 0x4f 0x16 0x90
0xf6 0x46 0x06 0xcf 0x38 0x59 0x45 0xb2 0xbe 0xc4 0xea. This value
is then base64-encoded, to give the value
"s3pPLMBiTxaQ9kYGzzhZRbK+xOo=", which would be returned in the
|Sec-WebSocket-Accept| header field.
注意:举一个例子,假如客户端握手Sec-WebSocket-Key头字段的值是 "dGhlIHNhbXBsZSBub25jZQ==",服务端追加"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"字段形成字符串:"dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11"。服务端然后对该串做SHA-1 散列加密,形成0xb3 0x7a 0x4f 0x2c 0xc0 0x62 0x4f 0x16 0x900xf6 0x46 0x06 0xcf 0x38 0x59 0x45 0xb2 0xbe 0xc4 0xea.这个值进行base64编码,形成"s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",最终被当做|Sec-WebSocket-Accept| 头信息返回给客户端。

5. Optionally, a |Sec-WebSocket-Protocol| header field, with a
value /subprotocol/ as defined in step 4 in Section 4.2.2.
可选的,Sec-WebSocket-Protocol头字段以子协议为值。

6. Optionally, a |Sec-WebSocket-Extensions| header field, with a
value /extensions/ as defined in step 4 in Section 4.2.2. If
multiple extensions are to be used, they can all be listed in
a single |Sec-WebSocket-Extensions| header field or split
between multiple instances of the |Sec-WebSocket-Extensions|
header field.
可选的,Sec-WebSocket-Extensions字段的值是4.2.2节中第四步定义的扩展列表。如果允许多个扩展,它们可以在一个Sec-WebSocket-Extensions中列出,也可以划分成多个Sec-WebSocket-Extensions字段。

This completes the server’s handshake. If the server finishes these
steps without aborting the WebSocket handshake, the server considers
the WebSocket connection to be established and that the WebSocket
connection is in the OPEN state. At this point, the server may begin
sending (and receiving) data.
到这里就完成了服务端的握手。假如服务端完成了所有的步骤,没有终止WebSocket握手,服务端就认为该WebSocket连接建立成功并处于OPEN状态。到这,服务端就可以接收发送数据了。

4.3. Collected ABNF for New Header Fields Used in Handshake
收集在握手中使用到的新的头字段

This section is using ABNF syntax/rules from Section 2.1 of
[RFC2616], including the "implied *LWS rule".
该节使用2.1节中的ABNF语法/规则,包括"implied *LWS rule"。

Note that the following ABNF conventions are used in this section.
Some names of the rules correspond to names of the corresponding
header fields. Such rules express values of the corresponding header
fields, for example, the Sec-WebSocket-Key ABNF rule describes syntax
of the |Sec-WebSocket-Key| header field value. ABNF rules with the
"-Client" suffix in the name are only used in requests sent by the
client to the server; ABNF rules with the "-Server" suffix in the
name are only used in responses sent by the server to the client.
For example, the ABNF rule Sec-WebSocket-Protocol-Client describes
syntax of the |Sec-WebSocket-Protocol| header field value sent by the
client to the server.
注意下面这些ABNF约定,在本节中用到了。一些规则的名称与一些头字段的名称对应。这些规则展示相应的头字段的值,例如,Sec-WebSocket-Key ABNF规则描述了|Sec-WebSocket-Key|头字段值得语法。ABNF中以"-Client"最为后缀的规则仅仅用在从客户端发往服务端的请求中;ABNF中以”-Server“结尾的规则仅仅用在从服务端发往客户端的响应中。例如,Sec-WebSocket-Protocol-Client 规则描述了由客户端发往服务端的Sec-WebSocket-Protocol头字段的值。

The following new header fields can be sent during the handshake from
the client to the server:
以下的新的头字段可以在从客户端发送服务端的握手中发送:
Sec-WebSocket-Key = base64-value-non-empty
Sec-WebSocket-Extensions = extension-list
Sec-WebSocket-Protocol-Client = 1#token
Sec-WebSocket-Version-Client = version
base64-value-non-empty = (1*base64-data [ base64-padding ]) |
base64-padding
base64-data = 4base64-character
base64-padding = (2base64-character "==") |
(3base64-character "=")
base64-character = ALPHA | DIGIT | "+" | "/"
extension-list = 1#extension
extension = extension-token *( ";" extension-param )
extension-token = registered-token
registered-token = token

extension-param = token [ "=" (token | quoted-string) ]
; When using the quoted-string syntax variant, the value
; after quoted-string unescaping MUST conform to the
; ’token’ ABNF.
NZDIGIT = "1" | "2" | "3" | "4" | "5" | "6" |
"7" | "8" | "9"
version = DIGIT | (NZDIGIT DIGIT) |
("1" DIGIT DIGIT) | ("2" DIGIT DIGIT)
; Limited to 0-255 range, with no leading zeros


The following new header fields can be sent during the handshake from
the server to the client:
以下的新头字段可以从服务端到客户端的握手中发送。
Sec-WebSocket-Extensions = extension-list
Sec-WebSocket-Accept = base64-value-non-empty
Sec-WebSocket-Protocol-Server = token
Sec-WebSocket-Version-Server = 1#version


4.4. Supporting Multiple Versions of WebSocket Protocol
支持多个版本的WebSocket 协议

This section provides some guidance on supporting multiple versions
of the WebSocket Protocol in clients and servers.
本节为在客户端和服务端使用多个版本的WebSocket协议提供了一些指导。

Using the WebSocket version advertisement capability (the
|Sec-WebSocket-Version| header field), a client can initially request
the version of the WebSocket Protocol that it prefers (which doesn’t
necessarily have to be the latest supported by the client). If the
server supports the requested version and the handshake message is
otherwise valid, the server will accept that version. If the server
doesn’t support the requested version, it MUST respond with a
|Sec-WebSocket-Version| header field (or multiple
|Sec-WebSocket-Version| header fields) containing all versions it is
willing to use. At this point, if the client supports one of the
advertised versions, it can repeat the WebSocket handshake using a
new version value.
通过WebSocket的版本广告功能(Sec-WebSocket-Version头字段),客户端可以先采用它更期望的WebSocket版本(不一定是客户端最新支持的版本)进行请求。假如服务端支持请求的版本而且握手信息也有效,服务端将接受那个版本。假如服务端不支持这个版本,它必须通过Sec-WebSocket-Version(或者是多个Sec-WebSocket-Version)进行响应,说明它所支持的所有版本信息。这时,如果客户端支持建议版本中的一个,它可以使用新版本重复WebSocket握手。

The following example demonstrates version negotiation described
above:
下面的例子展示了上面描述的版本转换过程:

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
...
Sec-WebSocket-Version: 25

The response from the server might look as follows:
HTTP/1.1 400 Bad Request
...
Sec-WebSocket-Version: 13, 8, 7
Note that the last response from the server might also look like:
HTTP/1.1 400 Bad Request
...
Sec-WebSocket-Version: 13
Sec-WebSocket-Version: 8, 7
The client now repeats the handshake that conforms to version 13:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
...
Sec-WebSocket-Version: 13

这篇关于RFC6455-The WebSocket protocol 之五:Opening Handshake 4.2-4.4的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1129095

相关文章

Java Websocket实例【服务端与客户端实现全双工通讯】

Java Websocket实例【服务端与客户端实现全双工通讯】 现很多网站为了实现即时通讯,所用的技术都是轮询(polling)。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发 出HTTP request,然后由服务器返回最新的数据给客服端的浏览器。这种传统的HTTP request 的模式带来很明显的缺点 – 浏 览器需要不断的向服务器发出请求,然而HTTP

【CSS in Depth 2 精译_024】4.2 弹性子元素的大小

当前内容所在位置(可进入专栏查看其他译好的章节内容) 第一章 层叠、优先级与继承(已完结) 1.1 层叠1.2 继承1.3 特殊值1.4 简写属性1.5 CSS 渐进式增强技术1.6 本章小结 第二章 相对单位(已完结) 2.1 相对单位的威力2.2 em 与 rem2.3 告别像素思维2.4 视口的相对单位2.5 无单位的数值与行高2.6 自定义属性2.7 本章小结 第三章 文档流与盒模型(已

Cannot read property ‘length‘ of null while opening vscode terminal

同一问题地址:Cannot read property ‘length’ of null while opening vscode terminal 问题描述 One day, 我在ubuntu 18.04下用vscode打开一个项目,并想和往常一样在vscode使用终端,发现报错Cannot read property 'length' of null。 解决 打开setting.jso

springboot websocket 服务端

在Spring Boot中使用WebSocket实现服务端和Java客户端的实时通信,可以分为几个步骤来完成。这里将详细介绍服务端和Java客户端的具体实现。 服务端设置 添加依赖: 在pom.xml文件中添加Spring WebSocket的依赖。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spr

ubuntu16.04 下 android 4.4.4 源码编译

文章目录 环境依赖编译过程问题1、MODULE.TARGET.SHARED_LIBRARIES.xxx already defined by xxx2、make: **** No Rule to make target "hardware/qcom/sm8150p/Android.mk" Stop 编译成功结果参考 环境依赖 java: 1.6make:3.81python:2.

Spring boot 项目作为客户端调用 服务端websocket

文章目录 java客户端请求websocketSpring boot 导入包客户端调用方法测试执行方法connectWebSocketHandshakeMessagesendHandshakeWebSocketConfig.queue.take方法对应实体类配置 yaml 资源WebSocketConfig 配置类注入配置websocketUrl:LinkedBlockingQueueLin

WebSocket+Spring boot 构建一个完整消息服务

1、添加依赖 compile project(":faas-spring-boot-starter-data-websocket") 2、定义WebSocketHandler Socket 服务入口(Header接收 jwt-token 同应用登录的Token(直接解决鉴权问题),然后定义请求的自定义参数,方便后续消息推送、支持群发、私发、模糊匹配) @Component@WebSock

spring-websocket基于stomp实现websocket

目录 概述 后端代码 拦截器 HandshakeInterceptor拦截器 ChannelInterceptor拦截器   消息转换器  配置类  消息处理 广播模式   用户模式 自定义请求头 用户信息  ChannelInterceptor拦截器设置用户信息  DefaultHandshakeHandler的继承类中设置用户对象 前端代码 概述

【python requests错误】Caused by SSLError(SSLError(bad handshake: SysCallError(104, 'ECONNRESET')

错误描述: 在发送get请求时错误,执行下面一句时报错了: response = requests.get(image_url) 原因HTTPSConnectionPool(host='test-kkbuluo-resource.cdn.hzmltest.com', port=443): Max retries exceeded with url: /IMCORE/RESOURCE/LOG

Nodejs 串口通信 : websocket , serialport

最近在学习如何实现web页面和串口间通信,网页请求使用websocket,实现的基本功能如下: 1、基本需求:硬件:有两个信号灯(TLA-505-1T),一个485继电器(开关),电压转换器,工业触屏一体机。 2、原理图:                  3工作原理: 首先一体机中采用node开发服务器,网页请求采用websocket协议,直接放代码了: var express