Есть ли способ установить tcp-соединение с IP-адресом с помощью javascript?

Позвольте мне немного рассказать о том, чего я пытаюсь достичь.

У меня есть устройство (чип и контактный терминал), которое имеет локальный IP-адрес. Оно запрограммировано на получение определенных данных и их обработку.

пример: я отправляю строку "05" в шестнадцатеричном формате "30 35", и терминал читает это и перезагружается.

Я пытался использовать 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 может это сделать?

Пожалуйста, спрашивайте, если что-то неясно, и я постараюсь уточнить.


person Derek    schedule 08.01.2016    source источник
comment
Почему важно подключаться к локальному сетевому устройству через JS? Разве нельзя было бы сделать это на сервере и провести транзакцию через события AJAX?   -  person Nathan    schedule 09.01.2016
comment
Выберите другой язык, почти ЛЮБОЙ другой язык, и он относительно прост, но (браузерный) JavaScript просто не делает этого по замыслу. В противном случае проводить отраженные атаки было бы детской забавой.   -  person symcbean    schedule 09.01.2016


Ответы (3)


Вы не можете установить простое TCP-соединение из Javascript в браузере, которое позволит вам отправлять данные в вашем собственном формате данных или протоколе. Браузер просто не поддерживает это.

Это позволяет вам делать запросы Ajax и соединения WebSocket. Запросы Ajax и WebSocket начинают свою жизнь как HTTP-запросы. В случае запроса веб-сокета HTTP-запрос может быть «обновлен» до протокола веб-сокета после того, как обе стороны согласятся, но исходные данные, отправленные на сервер, будут законным HTTP-запросом. Полный обзор как работает протокол webSocket от подключения к фактическому формату пакета. Даже после обновления до протокола webSocket он должен использовать формат кадрирования 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-запроса, является началом соединения через веб-сокет. Вот как это работает.

Если вы используете Javascript в небраузерной среде, такой как node.js, вы можете использовать модуль «net» для создания простого сокета TCP, который затем можно использовать с любым протоколом, который вы хотите.

person jfriend00    schedule 09.01.2016
comment
Отличное объяснение. Короче говоря, в браузере невозможно установить чистое TCP-соединение, поскольку протокол представляет собой HTTP более высокого прикладного уровня. - person Downhillski; 05.12.2016
comment
Почему минус? Какая часть этого неверна или нуждается в улучшении? - person jfriend00; 01.03.2017

В конце концов я нашел решение.

Что мне нужно было сделать, так это создать приложение Windows, которое будет действовать как сервер веб-сокетов.

При установке программы она создаст схему 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-адрес, который запускает программу. Веб-сокет будет создан и отправлен на запущенную программу сервера localhost:port.

Программа Windows сделает все, чтобы получить данные, а затем отправить их в виде необработанных байтов tcp/ip на терминал. Как только терминал отправляет данные обратно в программу Windows, программа Windows затем пересылает их обратно в веб-сокет, чтобы браузер мог обработать информацию.

Затем программа Windows уничтожит все соединения и завершит работу.

person Derek    schedule 06.04.2017

Вы пытались использовать так:

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

надеюсь, что я мог быть полезным!

person Marcos Almeida    schedule 08.01.2016
comment
Когда я изменяю свой код на этот, я вижу, что он отправляет те же теги, SYN ETX SOH - person Derek; 08.01.2016
comment
Это ответ ASCII!! SYN->синхронный холостой ход, ETX->конец текста и SOH->начало заголовка.. Это не имеет для меня особого смысла... что этот чип должен делать с 05, который вы ему отправляете? Каков протокол ответа чипа? - person Marcos Almeida; 08.01.2016
comment
Терминал прочитает 05 в шестнадцатеричном формате, что равно 3035. Машина узнает эту команду и перезапустится. Я не могу перепрограммировать, как терминал взаимодействует с данными, которые он получает. Я просто знаю, что мне не нужно отправлять какие-либо дополнительные шестнадцатеричные символы для начала или конца текста. Можно ли как-то его удалить, чтобы я отправлял ему необработанные данные без дополнительных тегов? - person Derek; 08.01.2016
comment
Ну, во-первых: вы уверены, что 05 — это 3035 в шестнадцатеричном формате? Терминал получает только 05, не нужно ассоциировать имя ключа, например: exampleSocket.send(JSON.stringfy({id:05})); - person Marcos Almeida; 08.01.2016
comment
Да, я знаю, что это правильное шестнадцатеричное значение. По той причине, что веб-сокет добавляет кучу дополнительной информации. Когда я запускаю его с программой С#, которая работает правильно, я вижу в WireShark отправку 2 байтов, то есть 05, однако, когда я перехватываю веб-сокеты, отправляющие данные, я вижу, что он отправляет 156 байтов данных, когда я только говорю ему отправить 05 - person Derek; 08.01.2016
comment
попробуйте использовать: var exampleSocket = new WebSocket('wss://IP:PORT'); примерSocket.binaryType = буфер массива; Если это не сработает, я не верю, что javascript будет работать без nodejs, есть некоторые библиотеки, которые дадут вам потрясающий результат! - person Marcos Almeida; 08.01.2016
comment
Я пробовал это и все еще получаю 156 байтов вместо 2. Я осмотрелся, кажется, что веб-сокеты изначально отправляют на сервер запрос на изменение протоколов с http на веб-сокет. Я предполагаю, что нет никакого способа обойти это. - person Derek; 08.01.2016
comment
Ага. вот почему вам нужно что-то для запуска от сервера к серверу... Я считаю, что для вашей работы с javascript вам, вероятно, придется взглянуть на вашу конечную точку. хорошо извините, я не мог много помочь... удачи! И если вы найдете что-то, пожалуйста, поделитесь! - person Marcos Almeida; 08.01.2016