【问题标题】:Is there a way to do a tcp connection to an IP with javascript?有没有办法使用 javascript 与 IP 建立 tcp 连接?
【发布时间】:2017-04-07 03:37:53
【问题描述】:

让我简要介绍一下我想要完成的工作。

我有一个具有本地 IP 地址的设备(芯片和引脚终端),它已被编程为接收某些数据并对其进行处理。

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

我尝试过使用SockJS-Client 以及内置的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 Sever 才能解释传入的数据。

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 是否可以做到这一点?

如果有什么不清楚的地方请询问,我会尽力澄清。

【问题讨论】:

  • 为什么通过JS连接本地网络设备很重要?难道不能在服务器上这样做并通过 AJAX 事件进行交易吗?
  • 选择另一种语言,几乎可以选择任何其他语言,而且它相对简单,但是(浏览器)JavaScript 根本不是设计来这样做的。否则,进行反射攻击将是小菜一碟。

标签: javascript websocket sockjs


【解决方案1】:

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

它只允许你进行 Ajax 请求和 WebSocket 连接。 Ajax 和 WebSocket 请求都以 HTTP 请求开始。在webSocket请求的情况下,HTTP请求在双方同意后可以“升级”为webSocket协议,但发送给服务器的初始数据将是合法的HTTP请求。您可以查看this MDN reference,了解从连接到实际数据包格式的 webSocket 协议如何工作的完整概要。即使升级到 webSocket 协议,它也必须对here 描述的所有数据使用 webSocket 帧格式。

以下是 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 连接的开始。这就是它的工作原理。

如果您在 node.js 等非浏览器环境中使用 Javascript,您可以使用“net”模块创建一个普通的 TCP 套接字,然后您可以使用任何您想要的协议。

【讨论】:

  • 很好的解释。总之,在浏览器中,不可能建立纯TCP连接,因为协议是更高的应用层HTTP。
  • 为什么投反对票?其中哪一部分不正确或需要改进?
【解决方案2】:

我终于找到了解决办法。

我要做的是创建一个 Windows 应用程序来充当 websocket 服务器。

安装程序时,它将创建一个 URI 方案,以便能够从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 程序随后将终止所有连接并退出。

【讨论】:

    【解决方案3】:

    你有没有试过这样使用:

    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);
    };
    

    希望我能有所帮助!

    【讨论】:

    • 当我将代码更改为该代码时,我看到它正在发送相同的标签,SYN ETX SOH
    • 这是一个 ASCII 响应!! SYN-> 同步空闲,ETX-> 文本结束和 SOH-> 标题开始.. 这对我来说没有多大意义......这个芯片应该如何处理你发送给它的“05”?芯片做出响应的协议是什么?
    • 终端将读取十六进制的“05”,即“3035”机器将知道该命令并自行重启。我无法重新编程终端如何与其接收的数据交互。我只知道我不需要为文本的开头或文本的结尾发送任何额外的十六进制字符。反正有没有剥离它,所以我在没有额外标签的情况下向它发送“原始”数据?
    • 好吧,首先:你确定“05”是十六进制的“3035”吗?终端 ii 只接收“05”,不需要关联一个键名,例如:exampleSocket.send(JSON.stringfy({id:"05"}));
    • 是的,我知道这是正确的十六进制值,因为 websocket 添加了一堆额外的信息,当我使用正常工作的 c# 程序运行它时,我在 WireShark 上看到发送2 个字节,即 05,但是当我捕获发送数据的 WebSockets 时,我看到它发送了 156 个字节的数据,而我只告诉它发送“05”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-10
    • 2019-06-30
    • 2010-11-03
    • 2012-11-11
    • 1970-01-01
    相关资源
    最近更新 更多