有没有办法用 javascript 建立到 IP 的 tcp 连接?

Is there a way to do a tcp connection to an IP with javascript?

让我简要介绍一下我正在努力完成的工作。

我有一个具有本地 IP 地址的设备(芯片和 pin 终端),它已被编程为接收特定数据并处理它。

示例:我以十六进制 "30 35" 形式发送字符串 "05",终端读取该字符串并重新启动。

我试过使用SockJS-Client as well as the built in WebSockets

但是使用 Websockets 我注意到浏览器正在发送:

GET / HTTP/1.1
Host: IP:PORT
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
Origin: MYIP
Sec-WebSocket-Version: 13
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
Sec-WebSocket-Key: A1CeTMFnQCZv4GNZbLFnyQ==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits

当我的代码如下所示时:

var exampleSocket = new WebSocket("ws://IP:PORT");

exampleSocket.send("05");

如果我将代码更改为:

var exampleSocket = new WebSocket("wss://IP:PORT");

exampleSocket.send("05");

我刚收到 3 个发送的标签:SYN(0x0016) ETX(0x0003) SOH(0x0001)

现在我不确定你是否需要一个 WebSocket 服务器来解释传入的数据。

SockJS 通过发送关于自身和浏览器的额外信息来做同样的事情:

GET /info?t=1452272641278 HTTP/1.1
Host: IP:PORT
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36
Origin: MYIP
Accept: */*
Referer: MYIP
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8

所以我想我的问题是。有没有办法只发送我想要的内容?没有任何额外数据?

我已经用 Objective-C 和 C# 完成了这个,我只是不确定 javascript 是否可以做到这一点?

有什么不明白的请追问,我会尽量解释清楚。

你试过这样使用吗:

var exampleSocket = new WebSocket('wss://IP:PORT', ['soap', 'xmpp']);

// When the connection is open, send some data to the server
exampleSocket.onopen = function () {
  exampleSocket.send('05'); 
};

// Log errors
exampleSocket.onerror = function (error) {
  console.log('WebSocket Error ' + error);
};

// Log messages from the server
exampleSocket.onmessage = function (e) {
  console.log('Server: ' + e.data);
};

希望我能帮到你!

您无法在允许您以自己的数据格式或协议发送数据的浏览器中从 Javascript 建立普通 TCP 连接。浏览器根本不支持。

它只允许您发出 Ajax 请求和 WebSocket 连接。 Ajax 和 WebSocket 请求都是从 HTTP 请求开始的。在webSocket请求的情况下,HTTP请求可以在双方同意后"upgraded"到webSocket协议,但是发送到服务器的初始数据将是一个合法的HTTP请求。可以看到this MDN reference for a whole outline of how the webSocket protocol works from connection to actual packet format. Even once it is upgraded to the webSocket protocol, then it must use the webSocket framing format for all data which is described here.

这里是 webSocket 数据帧格式的概述:

0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len |    Extended payload length    |
|I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
|N|V|V|V|       |S|             |   (if payload len==126/127)   |
| |1|2|3|       |K|             |                               |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
|     Extended payload length continued, if payload len == 127  |
+ - - - - - - - - - - - - - - - +-------------------------------+
|                               |Masking-key, if MASK set to 1  |
+-------------------------------+-------------------------------+
| Masking-key (continued)       |          Payload Data         |
+-------------------------------- - - - - - - - - - - - - - - - +
:                     Payload Data continued ...                :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
|                     Payload Data continued ...                |
+---------------------------------------------------------------+

因此,除非您的端点使用 HTTP 或 webSocket 协议,否则您无法从浏览器直接连接到它 Javascript。

您在问题中看到的初始 HTTP 请求是 webSocket 连接的开始。这就是它的工作原理。

如果您在 non-browser 环境中使用 Javascript,例如 node.js,您可以使用 "net" 模块创建一个普通的 TCP 套接字,然后您可以使用任何你想要的协议。

我终于找到了解决办法。

我必须做的是创建一个 windows 应用程序作为 websocket 服务器。

安装程序时,它会创建一个 URI 方案,以便能够从 link 中调用自己,例如 myapp://start

下面是编辑注册表以添加自定义 URI 方案的代码:

static void Main(string[] args) {

            try {

                // SET PATH OF SERVER
                String path = Environment.GetCommandLineArgs()[0];

                // GET KEY
                RegistryKey key = Registry.ClassesRoot.OpenSubKey("myApp");

                // CHECK FOR KEY
                if (key == null) {


                    // SET KEY
                    key = Registry.ClassesRoot.CreateSubKey("myApp");
                    key.SetValue(string.Empty, "URL: myApp Protocol");
                    key.SetValue("URL Protocol", string.Empty);

                    // SET COMMAND
                    key = key.CreateSubKey(@"shell\open\command");
                    key.SetValue(string.Empty, path + " " + "%1");
                    //%1 represents the argument - this tells windows to open this program with an argument / parameter


                }

                // CLOSE
                key.Close();

            } catch (Exception ex) {
                Console.WriteLine(ex.Message);
                Console.ReadKey();

            }



}

然后在浏览器中它将调用启动程序的 url。 将创建 websocket 并将其发送到 localhost:port 服务器程序 运行.

windows 程序将尽一切努力获取数据,然后将其作为原始 tcp/ip 字节发送到终端。 一旦终端将数据发送回 windows 程序,windows 程序会将其转发回 websocket 以供浏览器处理信息。

然后 windows 程序将终止所有连接并退出。