Откройте соединение TCP/IP через сокет с помощью принтера этикеток

Я хочу открыть соединение TCP/IP с принтером Zebra для отправки команд ZPL на печать. Я могу сделать это с помощью NodeJS, но не с помощью веб-сокетов.

NodeJS

var s = require('net').Socket();
s.connect(9100, '192.168.0.99');
s.write(zpl_commands);

но не могу отправлять команды через веб-сокет, я не хочу создавать промежуточный сервер с NodeJS, который печатает. Есть идеи, смогу ли я добиться этого? Я уже пытался создать плагин для Chrome, но не получилось.

Мой код веб-сокета

const socket = new WebSocket('ws://192.168.0.99:9100');

socket.send(message);

Мне нужно работать с Chrome, потому что я подключаю весовой тренажер через последовательный порт. Возможно решение подключить принтер к компьютеру через кабель (но мне хотелось бы через Wi-Fi, чтобы можно было печатать с нескольких терминалов) Примечание: если вставить в браузере ws://..., я смогу подключиться к принтеру printServer. Примечание 2. Это принтер Zebra ZD420.

Ваш принтер не поддерживает WebSockets. Почему вы ожидаете, что это будет работать именно так? Сетевой сокет, независимо от того, TCP или UDP, не является автоматически WebSocket. WebSocket работает на более высоком уровне, чем TCP-сокеты. en.wikipedia.org/wiki/OSI_model tcp/udp уровень 4, http/ws = уровень 7

Marc 29.06.2024 00:18

@Марк Я читал в документе Zebra, что некоторые принтеры поддерживают WebSocket, а у меня есть «сервер печати», но я думаю, что он работает только для конфигураций. Но есть ли способ подключить веб-приложение Chrome на нижнем уровне? Мое текущее решение состоит в том, чтобы создать промежуточное приложение NodeJS, чтобы веб-приложение отправляло сигнал печати на сервер, а затем сервер на клиент принтера.

Eduardo Iglesias 29.06.2024 00:24

Вы можете написать «прокси», который предоставляет сервер/конечную точку WebSocket и пересылает его на ваш принтер. (github.com/novnc/websockify , github.com/erebe/wstunnel , github.com/mhzed/wstunnel). Где вы прочитали, что некоторые принтеры поддерживают WebSockets? Теоретически это возможно, но я не понимаю/понимаю, почему производитель принтеров реализует/делает это. WebSockets обычно не являются способом указать принтеру, что делать. Существуют другие стандарты/реализации, соответствующие этому требованию.

Marc 29.06.2024 00:32

Быстрый поиск по ключевым словам «Веб-сокет Zebra ZD420»: When connected to a wired or wireless network, the printer attempts to connect to Zebra's Asset Visibility Service through the cloud-based Zebra Printer Connector using an encrypted, certificate-authenticated web socket connection. Это не означает, что вы можете указать принтеру через WebSocket, что печатать. Если вас устраивает мой подход через прокси, я бы предложил возможное решение.

Marc 29.06.2024 00:36

@Марк, очевидно, я не понимаю, потому что веб-сокет. Что касается прокси, я думал о написании небольшого локального сервера, который перенаправляет команды ZPL на принтер, конечно, пользователю нужно установить дополнительную программу, которая будет работать в фоновом режиме и открывать локальный порт 24/7, но это промышленный вариант. Приложение Я уверен, что это не имеет значения. Итак, теперь через сокеты я буду отправлять данные из сети на локальный сервер. Думаете, это похоже на решение?

Eduardo Iglesias 29.06.2024 00:42

Извините, я не знаю, что вы имеете в виду под «сокетами» или что вам не хватает понимания. Используйте четкие формулировки, например «Сетевые сокеты», которые относятся к сокетам TCP/UDP, или «WebSockets», которые относятся к более высоким протоколам, таким как HTTP/WebSocket, которые используют TCP в качестве транспорта.

Marc 29.06.2024 00:48

Плохо, я имею в виду, что я открываю небольшой локальный сервер в приложении NodeJS, который открывает веб-сокет, а затем веб-приложение отправляет ZPL на локальный сервер. Затем приложение NodeJS открывает сетевой сокет с принтером и отправляет все команды.

Eduardo Iglesias 29.06.2024 00:53

Точно. Вот как вам следует это сделать. Я опубликовал ответ, который реализует эту логику.

Marc 29.06.2024 00:58
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
8
107
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как указано в моем комментарии, принтер не поддерживает конечную точку WebSocket, куда вы можете отправлять ему команды.

Скорее вам нужно написать/использовать прокси, который создает конечную точку WebSocket/HTTP, которая перенаправляет отправленные на нее данные на базовый TCP-сокет, подключенный к принтеру.

const { WebSocketServer, createWebSocketStream } = require("ws");
const { Socket } = require("net");



const { 
    WEBSOCKET_HOST, 
    WEBSOCKET_PORT, 
    PRINTER_HOST, 
    PRINTER_PORT 
} = Object.assign({
    WEBSOCKET_HOST: "127.0.0.1",
    WEBSOCKET_PORT: "8320",
    PRINTER_HOST: "127.0.0.1",
    PRINTER_PORT: "1900"
}, process.env);


const server = new WebSocketServer({
    port: Number(WEBSOCKET_PORT),
    host: WEBSOCKET_HOST
});


server.once("listening", () => {
    console.info(`WebSocket server listening on ws://${WEBSOCKET_HOST}:${WEBSOCKET_PORT} for connections`);
});


server.on("connection", (ws) => {

    let socket = new Socket();
    let stream = createWebSocketStream(ws);

    socket.once("connect", () => {
        console.info("Connected to printer");
    });

    // pipe data from websocket to tcp socket
    // pipe data from tcp socket to websocket
    stream.pipe(socket);
    socket.pipe(stream);

    // connecto to printer via tcp socket
    socket.connect(Number(PRINTER_PORT), PRINTER_HOST);

});

Приведенный выше код очень прост и понятен.

Он создает сервер/конечную точку HTTP/WebSocket, к которому могут подключаться клиенты (например, браузер, wscat и т. д.), который затем создает TCP-сокет для принтера.

Вы можете проверить это с помощью netcat и wscat.

Сначала создайте фиктивный TCP-сервер/принтер с помощью: nc -l -p 1900. Это указывает netcat создать TCP-сокет для входящих запросов на интерфейсе обратной связи (127.0.0.1) на порту 1900.

Запустите прокси-сервер WebSocket, указанный выше (после установки модуля websocket через npm install ws): node tcp-ws-proxy.js.

Наконец, подключитесь через клиент WebSocket CLI wscat --connect ws://127.0.0.1:8320 и введите некоторые данные, например. «Привет, Netcat».

Все, что вы вводите, должно быть напечатано на консоли/терминале/выходе netcat.

Это позволяет вам подключаться к принтеру через клиент WebSocket, например браузер.

Используемые модули/инструменты CLI:

Написано и протестировано на Ubuntu 23.10, Node 20.11.0.

Обновлено:

Поскольку Берги упомянул об этом в комментариях, я должен был упомянуть, что вам необходимо должным образом защитить конечную точку WebSocket. В противном случае каждый мог бы отправлять команды печати на принтер.

«Код очень прост и понятен» — и небезопасен. Если вы предоставляете такие привилегированные функции через веб-сокеты, вы должны проверить заголовок origin! В противном случае любая произвольная веб-страница, которую открывает пользователь, может начать печатать все, что захочет.

Bergi 29.06.2024 01:32

Конечно, в этом нет никаких сомнений. Код представляет собой эталонную реализацию, а не решение типа «копировать и вставить». С каких это пор SO является решением «идеально скопировать это и напечатать на этом деньги»? Механизм аутентификации уничтожит этот ответ/вопрос, поскольку никто не знает, как ОП хочет его использовать. Если вы знаете лучшее решение, не стесняйтесь создать ответ. Кстати: исходным заголовком можно манипулировать, или его можно полностью обойти, если он используется с помощью инструментов CLI, таких как wscat, поэтому ваш «механизм безопасности» также является ужасным инструментом и змеиным маслом. Мой код является примером того, как это можно сделать.

Marc 29.06.2024 01:41

Ответ, в котором здесь даже не упоминается аутентификация, является плохим ответом. Проверка происхождения будет проста в реализации (просто передайте обратный вызов verifyClient). И нет, заголовком origin нельзя манипулировать с помощью клиентов браузера, что является проблемой, поскольку они выполняют произвольный ненадежный код. Другие клиенты в сети в любом случае могут просто открыть TCP-соединение напрямую с принтером.

Bergi 29.06.2024 01:51

Если у вас есть общедоступная конечная точка WebSocket, кого волнуют браузеры? And no, the origin header cannot be manipulated by browser clients (which are the issue here). Верно, но злоумышленник все равно может отправить в таком заголовке все, что захочет, поэтому использовать это в качестве соображения безопасности просто глупо...

Marc 29.06.2024 01:54

ОП написал: «Я думал о написании небольшого локального сервера, который перенаправляет команды ZPL на принтер, конечно, пользователю нужно установить дополнительную программу, которая будет работать в фоновом режиме и открывать локальный порт 24 часа в сутки, 7 дней в неделю, но это промышленный вариант». application», поэтому я предположил, что это будет не общедоступная (в Интернете) конечная точка, а скорее приложение, установленное на том же компьютере, что и браузер, на котором запущено веб-приложение (или, по крайней мере, в той же интрасети, что и принтер). Что касается общедоступной конечной точки, вы совершенно правы, сценарий угроз там другой, и аутентификация не может полагаться только на origin.

Bergi 29.06.2024 02:00

И? То, что вы думаете, и то, что делает ОП, совершенно разные. Если это запускается на компьютере, к которому имеет доступ только локальный пользователь/браузер, то почему так злитесь на аутентификацию? Здесь на ТАК много страшных угроз безопасности, а ты без ума от принтера? Я добавил примечание о безопасности в свой ответ. Расслабься, братан.

Marc 29.06.2024 02:04

«Если это запускается на компьютере, к которому имеет доступ только локальный пользователь/браузер, то почему вы так злитесь на аутентификацию?» — именно потому, что это небезопасно, с риском, который легко упустить из виду: локальный браузер может открывать произвольные веб-сайты, не только ваши, и все они могут иметь доступ к конечной точке веб-сокета в равной степени — за исключением заголовка origin.

Bergi 29.06.2024 02:07

У вас есть пункт. Можете ли вы объяснить более подробно, как будет выглядеть атака? Я думаю, что я неправильно вас понял в первую очередь. Как веб-сайт example.com может получить доступ к конечной точке веб-сокета на 127.0.0.1 или 192.168.4.210. Просто позвонив new WebSocket("ws://127.0.0.1:8320")? Это действительно было бы угрозой безопасности. Но разве злоумышленник не должен знать, что такой сервис прослушивает?

Marc 29.06.2024 02:12

Да, создать new WebSocket("ws://127.0.0.1:8320") достаточно. Не существует политики одинакового происхождения или аналогичной политики, которая препятствовала бы доступу к сокету. Но да, злоумышленнику, вероятно, нужно будет заранее узнать об этой службе, я сомневаюсь, что в дикой природе появится универсальное вредоносное ПО, сканирующее порты и угадывающее протокол. Но если вы станете мишенью или даже если это приложение для печати станет достаточно распространенным, чтобы хакер на него мог обратить внимание, они могут написать специальный вирус… просто ради развлечения!

Bergi 29.06.2024 05:15

Спасибо! И на самом деле я отправлю уникальный код задания печати, который сервер должен проверить на моем API, существует ли уникальный идентификатор задания печати, и вернуть команды ZPL.

Eduardo Iglesias 29.06.2024 06:49

Другие вопросы по теме

Похожие вопросы

Можно ли предварительно обработать дискриминатор в дискриминируемом объединении zod?
Лучшая практика асинхронного получения данных API из разных конечных точек с помощью React?
Где хранятся анонимные функции обратного вызова для setTimeout?
Добавить числа в объект в массиве JavasScript из индекса ниже значения и возвращаемого значения
Печать и предварительный просмотр веб-страницы не работают должным образом в браузере Microsoft Edge
Возврат значений на страницу Razor — запутанный Javascript или .cs?
Сборка npm run не удалась из-за несовместимости машинописного текста или lodash
TypeScript «Нет перегрузки, соответствующей этому вызову»
Способ определения точных свойств стиля, которые в данный момент применяются веб-анимацией (без смешивания со всеми применяемыми в данный момент стилями)
Как загрузить изображение на холст в Gradio с помощью специального HTML и JavaScript?