TP-Link TL-WR741N, как и любой другой, спокойно даёт пробросить порт 80. Вебсокет использует tcp. Проброс портов в родной прошивке tp-link работает точно так же, как и в open/dd/ху*-wrt. Дело, скорее всего, не в этом.
TP-Link TL-WR741N, как и любой другой, спокойно даёт пробросить порт 80. Вебсокет использует tcp. Проброс портов в родной прошивке tp-link работает точно так же, как и в open/dd/ху*-wrt. Дело, скорее всего, не в этом.
Конечно вебсокет работает по tcp. udp никоим боком. Просто челу "апоговорить" похоже. В любом случае не нужно его на 80-й порт вешать. То что TP-Link должен иметь возможность настраиватся на проброс 80 как бы ожидаемо, иначе дома и апачу не развернеш с домашним сайтом.
Ты читать не умеешь ? Где я написал, что не доволен !? Не нужно читать между строк.
Здесь!
brokly пишет:
Я не знаю как это библиотека построена для одно ядерной 8266, но для есп32 это не самое удачное "изделие".
Вообще все негативные отзывы от этой либе в теме - только от тебя. И про проблему больших данных и ссылки на список ошибок. Меня больше возмутило обобщение проблем аж до асинхронного веба. Ну кривая либа (возможно, ты ж о ней такое пишеш), ну некоторые не поняли как ее дергать. Тоже мне новости. Обобщать с ссылкой на "что у огромной массы людей асинхронный веб вызывает стойкую аллергию" не стоит, твои пацаны на районе не тянут просто ;)
brokly пишет:
Кстати ты смысл своего первого предложения на русский не переведешь ? Что ты хотел сказать ? Что ТС не использует , как ты выразился "кривую либу тупого автора" ? Или что ? Так , на всякий случай, я говорил именно о библиотеке
И я о библиотеке и ее авторе, о чем жеж еще, все ты понял.
brokly пишет:
И еще раз повторю, проблема этой библиотеки на ESP32 в том, что в колбэках нельзо долго оставаться. С ними нужно работать практически как с прерываниями, потому как они из другого потока.
У тя каша в башке, потому то прерывания, то как бы прерывания то другой поток. Ты похоже имел в виду что луп и калбеки в разных потоках и требуют синхронизации... Та неважно, забей, то слишком сложно.
Кстати можно или нельзя долго оставаться - это совсем не к свойствам калбека или потока, это к качеству либы. И судя по твоим словам, подчеркиваю, именно по твоим словам!!!, не отнекивайся и стрелки не переводи, либа таки действительно кривая.
Потому как таких страстей-мордастей протокол вебсокета вобще не требует. Как и ТСР в общем. Вебсокет тупо на нем построен и если есть проблема приема больших данных - см. стек ТСР. За некоторым исключением. Как чел, реализовавший себе этот протокол, отмечу, что вопросу длинны данных во фрейме (это терменология спеки на вебсокет) в протоколе особое внимание. Длина поляв котором эта самая длина данных передается переменная и применима для данных до 2^64 байт. А при коротких данных, до 125, свой формат, компактный. Уже из этого следует что проблемы принципиальной нет. А что там автор наваял, поддержал ли все кейсы или нет - на его совести. Я писал так.
long int Len=b[1]&0x7f;
long int Ofs;
switch (Len)
{
case 126:
Len=(uint16_t)b[2];
Ofs=4;
break;
case 127:
Len=(uint64_t)b[2];
Ofs=10;
break;
default:
Ofs=2;
}
Но насколько верно - я даже не знаю т.к. больших данных мне не попадалось. Ну вот так... Не тестил.
Далее. Эта самая длина, и прочая пурга из хедера - в начале фрейма, т.е. в одном tcp пакете с первыми байтами данных. Очевидно при длине данных до 125 у нас всегда все принято на момент парсинга хедера. И попытка получить данные сразу после парсинга будет успешная. А для данных почти 2^64 или около того - придется долго ждать пока приедут, стек ТСР их сложит и т.д. Как это согласовать с быстрой обработкой калбека - ХЗ, думал ли автор о проблеме - ХЗ, сталкивался ли ты с этим - ХЗ. Но похоже что либа не для этого случая..
Далее, обратил внимание, ТС хочет машинкой рулить. А это как бы значить, что клиент у вебсокета один. Тогда спрашивается, нахрена этот цирк с потоками который приводит к проблемам? И ситуация когда клиент один (реже 2-3 но не много) очень типичная для МК. А автор либы взял типовую архитектуру сервера, и каждому клиенту поток забецал. При скудных ресурсах создал доп проблемы. Это тоже не в плюс либе...
Продолжу тут, форум тупит. Так вот, накосячить в либе есть где. И с большими данными тоже. И ее архитектура, многопоточность, калбеки вызывает сомнения. Но это не повод писать о проблемах асинхронного веба и протокола вебсокет вобще. Свет клином на этой либе не сошолся. И тем более вопросы по либе к теме форума не относятся. У ТС в локалке работает. Причем тут либа. Разнесет порты, настроит проброс и заработает. Не смущайте чела почем зря.
Продолжу тут, форум тупит. Так вот, накосячить в либе есть где. И с большими данными тоже. И ее архитектура, многопоточность, калбеки вызывает сомнения. Но это не повод писать о проблемах асинхронного веба и протокола вебсокет вобще. Свет клином на этой либе не сошолся. И тем более вопросы по либе к теме форума не относятся. У ТС в локалке работает. Причем тут либа. Разнесет порты, настроит проброс и заработает. Не смущайте чела почем зря.
Не буду тут растекаться , как это делаешь ты. Придирки к словам , которые ты таскаешь из контекста - хрень ни о чем.
По теме. Дело в том, что скорость потока данных в локалке и из-вне разная. А это приводит к тому, что одни и те же обработки работают разное время. Я не буду тут жевать по буквам почему и как. НО любая асинхронная библиотека первым делом обращает внимание на то, что обработки выполняются в другом потоке нежели основной цикл. Как это достигнуто, с использованием прерываний, потоками, другими способами - значения не имеет. Но они должны быть короткие и правильно оперировать данными.
ЗЫ Ты когда пишешь так многостранично, ты думай зачем ты это делаешь. Я твое "полотенце" не читал. И не буду. Много есть на то причин. Основная - не интересно. Ты все равно ничего умного в таком количестве сказать не мог :)
ЗЫ Ты когда пишешь так многостранично, ты думай зачем ты это делаешь. Я твое "полотенце" не читал. И не буду.
И это тот кто обвинял меня в том что я не читаю сообщений! Ты вообще помнишь что пишеш тремя постами ранее?))) То то ты все не в попад отвечаешь, да порешь чушь. То прерывания, то потоки. Оно так в башке хаос и останется, если не читать. Вот и здесь, в трех предложениях столько ахинеи нанес..
brokly пишет:
Дело в том, что скорость потока данных в локалке и из-вне разная. А это приводит к тому, что одни и те же обработки работают разное время. Я не буду тут жевать по буквам почему и как. НО любая асинхронная библиотека первым делом обращает внимание на то, что обработки выполняются в другом потоке нежели основной цикл. Как это достигнуто, с использованием прерываний, потоками, другими способами - значения не имеет. Но они должны быть короткие и правильно оперировать данными.
Библиотека у него обращает внимание)) Та отдельные потоки для клиента как раз создают чтоб они работали независимо и тормоза одного не влияли на остальных. Это оправдано для ПК и как часто бывает не оправдано на МК. В том их отличие от обработчика прерывания в плане длительности исполнения. Ну ты ж не читаешь, ходи дальше дремучим. Считай твой культпросвет закончен, дальше я только время на тупицу потеряю. Если за шесть лет на форуме не понимаешь разницу между потоком и прерыванием - безнадежен.
Всё, что до этого было, я, естественно, не трону, пусь вам стыдно будет. Я просто к тому, что давайте цивилизованно вести дискуссию, без всяких "крысоухих змей" и прочего. :)
Всё, что до этого было, я, естественно, не трону, пусь вам стыдно будет. Я просто к тому, что давайте цивилизованно вести дискуссию, без всяких "крысоухих змей" и прочего. :)
А я и вел цивилизованно, пока не набежали "двое из ларца" и не стали умные советы бредом называть
мыслей нет, но выше 1024 это пользовательские порты, может в этом проблема
Это ни о чем не говорит. Относитесь к портам и их пробросу проще. Это я вам как цисковод с дипломами говорю ;)
начинать анализ надо с того, что открыть страничку с компьютера и посмотреть исходный код страницы, мне так кажется, если в коде косяков нет, то на локальной сети (не вайфай) открыть простейший сервер www и на него сделать проброс, если эта связка заработает, останется только бридж на вайфай... но проблемы могут быть и с MTU
Зачем все так усложнять ? Не в этом дело. Почему мы всегда пытаемся искать ошибки у других. Нужно искать у себя. Ошибка в коде ESP, она же сваливает в ошибку, значит кривой код. Если бы было все нормально, то с какого фига эксепшены возникали бы ? Есп это вам не мега328, есп даже на ноль делить не даст :)
Зачем все так усложнять ? Не в этом дело. Почему мы всегда пытаемся искать ошибки у других. Нужно искать у себя. Ошибка в коде ESP, она же сваливает в ошибку, значит кривой код. Если бы было все нормально, то с какого фига эксепшены возникали бы ? Есп это вам не мега328, есп даже на ноль делить не даст :)
он же говорит, что в локалке работает, проблем нет
Зачем все так усложнять ? Не в этом дело. Почему мы всегда пытаемся искать ошибки у других. Нужно искать у себя. Ошибка в коде ESP, она же сваливает в ошибку, значит кривой код. Если бы было все нормально, то с какого фига эксепшены возникали бы ? Есп это вам не мега328, есп даже на ноль делить не даст :)
он же говорит, что в локалке работает, проблем нет
Еще раз . Внимательно. ЕСП сваливается с ошибкой. Кто сваливается роутер ? Провайдер ? Так почему мы пытаемся роутер крутить ? Ну смешно :)
На зарезервированный. То бишь: я выяснил MAC адрес своей esp32 и связал ее MAC с ip адресом (в моем случае, внутренний адрес от роутера выдан такой: 192.168.0.106) в настройках роутера.
То есть: теперь при любом коннекте esp32 к роутеру- он ей выдает этот ip.
Ну и опять же: все видится снаружи, то бишь всё вроде работает. Но через задницу :-))))
и не надо выяснять МАС, надо просто назначить статический IP на девайс, добавить:
// Задайте свой статический IP-адрес
IPAddress local_IP(192, 168, 1, 240);
// Укажите IP-адрес шлюза
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(8, 8, 8, 8); // опционально
IPAddress secondaryDNS(8, 8, 4, 4); // опционально
void setup() {
Serial.begin(115200);
// переключаем контакты моторов в режим «OUTPUT»:
pinMode(motor1Pin1, OUTPUT);
pinMode(motor1Pin2, OUTPUT);
pinMode(motor2Pin1, OUTPUT);
pinMode(motor2Pin2, OUTPUT);
// подключаем контакты оптических датчиков к пину, в режим «INPUT»:
pinMode (SensorPin1, INPUT);
pinMode (SensorPin2, INPUT);
//подключаем реакцию на прерывания - к пинам датчиков:
// attachInterrupt(SensorPin1, sensor_impulse, LOW);
// attachInterrupt(SensorPin2, sensor_impulse2, LOW);
// задаем настройки ШИМ-канала каждого из 2 двигателей:
ledcSetup(pwmChannel, freq, resolution); // первый двигатель
ledcSetup(pwmChannel2, freq2, resolution2); // второй двигатель
// подключаем ШИМ-канал, к контактам для управления скоростью вращения каждого из 2 моторов:
ledcAttachPin(motor1Pin1, pwmChannel); // первый двигатель
ledcAttachPin(motor2Pin1, pwmChannel2); // второй двигатель
// подаем на контакты ШИМ-сигнал с коэффициентом заполнения «0»:
ledcWrite(pwmChannel, dutyCycle);
ledcWrite(pwmChannel2, dutyCycle2);
// Настраиваем статический IP-адрес сервера:
if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
Serial.println("STA Failed to configure"); // "Не удалось задать статический IP-адрес"
}
// Connect to Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
// Print ESP Local IP Address
Serial.println(WiFi.localIP());
initWebSocket();
// Route for root / web page
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html, processor);
});
// Start server
server.begin();
}// END SETUP
Залил скетч из примеров ESP32 для вэбсокета!
ДА! Через проброшенный порт не работает (OpenWrt, TP-LINK 842ND)
Пробрасываю порт 8080 на 80, а вот если пробрасывать 80 на 80 порт, то работает
На кроссоверных портах не устанавливается websocket соединение, так получается, осталось понять почему
Один и тот же код для проверки использую и для ESP8266 и для ESP32, только библиотеки разные...
Проверил сделав проброс с 8080 на 80 на ESP32 и, работает...скетч правда websocket не использует
Беру еще один пример. там где WS отрабатывает в обе стороны и, через проброшенный порт не работает ни на ESP8266 ни на ESP32, мало того и сервер на порту отличном от 80 не работает на обоих девайсах...
ДА УЖ с этим вэбсокетом всё не так просто
так оно не назначено было видимо!
Проверил и на esp8266 и на ESP32 в любых комбинациях портов работает, еще бы кнопку прилепить и индикатор, что от клиента до сервера и обратно отрабатывает...
Выходит дело было не в бобине? )))
PS Значит скетчи из инета с примерами вэбсокетов кривые, надо же а они информацию даже продают...
Не в бобине, а в непонимании принципа работы протокола. Скетчей "из интернета" я не видел. Может и кривые, а может и просто заточены под конкретную задачу.
Кнопки мне неинтересно приделывать, а вот демо клиентской части поустойчивей я сделал для тестов:
Заменил кусок, работает, сейчас сервер работает на 8000 порту а проброс снаружи делаю с порта 8080, сейчас еще пару правил в роутере добавлю, посмотрю
тестирую на 12 клиентах, я правильно понимаю, если обмен завис более чем на 2 секунды сокет переоткрывается?
Если клиент отвалился (штатно или нет), то следующая попытка переподключения будет произведена через 2 секунды.
прекрасная надёжность получается, напрашивается дополнить скетч подсчётом числа переподключений...
Для тестовых испытаний
Даже столь косметические изменения программы делают её работоспособной для доступа с наружней сети
Код конечно совсем кривой, ТС, ты бы поправил:
// взято отсюда - http://arduino.ru/forum/programmirovanie/probros-portov-ne-rabotaet-no-prichina-v-biblioteke-koda-vidimo?page=1#comment-568781
// изменено для работы со статическим IP адресом
#define ESP32 // Для ESP32 размаркировать
#ifdef ESP32
#include <WiFi.h>
#include <AsyncTCP.h>
const uint16_t ports = 8000;
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h> // https://github.com/me-no-dev/ESPAsyncTCP
const uint16_t ports = 8000;
#endif
#include <ESPAsyncWebServer.h>
// вставляем ниже SSID и пароль для своей WiFi-сети:
const char* ssid = "OpenWrt";
const char* password = "123456789";
// Create AsyncWebServer object on port
AsyncWebServer server(ports);
AsyncWebSocket ws("/ws");
// Задайте свой статический IP-адрес
IPAddress local_IP(192, 168, 1, 240);
// Укажите IP-адрес шлюза
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(8, 8, 8, 8); // опционально
IPAddress secondaryDNS(8, 8, 4, 4); // опционально
// переменная для хранения HTTP-запроса:
String header;
// мотор 1:
int motor1Pin1 = 21;
int motor1Pin2 = 19;
//int enable1Pin = 14;
// мотор 2:
int motor2Pin1 = 23;
int motor2Pin2 = 22;
//int enable2Pin = 32;
// переменные для свойств широтно-импульсной модуляции (ШИМ) 1-двигателя:
const int freq = 30000;
const int pwmChannel = 0;
const int resolution = 8;
int dutyCycle = 0;
// переменные для свойств широтно-импульсной модуляции (ШИМ) 2-двигателя:
const int freq2 = 30000;
const int pwmChannel2 = 1;
const int resolution2 = 8;
int dutyCycle2 = 0;
// переменные для расшифровки HTTP-запроса GET:
String valueString = String(5);
int pos1 = 0;
int pos2 = 0;
//------------------- Работа с оптическими датчиками --------------------------
String state; //сюда будет писаться состояние, т.е. куда едет машинка в данный момент
volatile uint32_t lasttime1 = 0;
volatile uint32_t lasttime2 = 0;
//Куда подключены оптические датчики энкодера:
int SensorPin1 = 13;
int SensorPin2 = 14;
volatile uint32_t gap1 = 0;
volatile uint32_t gap2 = 0;
//-----------------------------------------------------------------------------
//----------------PID регулятор-------------------------
//Величины PID регулятора
int setpoint = 0; // заданная величина, которую должен поддерживать регулятор
int input = 0; // сигнал с датчика (например температура, которую мы регулируем)
int output = 0; // выход с регулятора на управляющее устройство (например величина ШИМ или угол поворота серво)
int pidMin = 0; // минимальный выход с регулятора/Изначально тут стояло 0
int pidMax = 0; // максимальный выход с регулятора/Изначально тут стояло 255 - это число для 8-битного ШИМ
// коэффициенты
float Kp = 1.0; //тут стояло 1.0
float Ki = 1.0; //тут стояло 1.0
float Kd = 1.0; //тут стояло 1.0
float _dt_s = 0.1; // время итерации в секундах
// вспомогательные переменные
int prevInput = 0;
float integral = 0.0;
//------------------------------------------------------
//----------------PID регулятор (вариант2)-------------------------
// GyverPID regulator(0, 0, 0, 10);
//-----------------------------------------------------------------
//-------------------БЛОК РАБОТЫ С WEBSOCKET И ОТОБРАЖЕНИЯ ВЕБ-СТРАНИЦЫ----------------------------------------
bool ledState = 0;
const int ledPin = 2;
// Create AsyncWebServer object on port 80
// AsyncWebServer server(80);
// AsyncWebSocket ws("/ws");
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
<title>ESP Web Server</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:,">
<style>
html {
font-family: Arial, Helvetica, sans-serif;
text-align: center;
}
h1 {
font-size: 1.8rem;
color: white;
}
h2{
font-size: 1.5rem;
font-weight: bold;
color: #143642;
}
.topnav {
overflow: hidden;
background-color: #143642;
}
body {
margin: 0;
}
.content {
padding: 5 px; //30px;
display: flex;
justify-content: center;
// margin: 0 auto;
text-align: center;
// margin-left: auto;
// margin-right: auto;
}
.content2 {
padding: 5 px; //30px;
display: flex;
justify-content: space-between;
// // padding: px; //30px;
// max-width: 400px;
// margin: 0 auto;
}
.content3 {
padding: 40 px; //30px;
display: flex;
justify-content: center;
}
.button1 {
padding: 15px 50px;
font-size: 24px;
text-align: center;
outline: none;
color: #fff;
background-color: #0f8b8d;
border: none;
border-radius: 5px;
width: 670px;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-tap-highlight-color: rgba(0,0,0,0);
}
.button2 {
padding: 15px 5px;
font-size: 24px;
text-align: center;
outline: none;
color: #fff;
background-color: #0f008d;
border: none;
border-radius: 5px;
width: 140px;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-tap-highlight-color: rgba(0,0,0,0);
}
/*.button:hover {background-color: #0f8b8d}*/
.button:active {
background-color: #0f8b8d;
box-shadow: 2 2px #CDCDCD;
transform: translateY(2px);
}
.state {
font-size: 1.5rem;
color:#8c8c8c;
font-weight: bold;
}
</style>
<title>ESP Web Server</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:,">
</head>
<body>
<div class="content">
<p><button id="button" class="button1">forward</button></p>
</div>
<div class="content2">
<p><button id="button2" class="button2"><<< left</button></p>
<p><button id="button2_1" class="button2">< slow</button></p>
<p><button id="button3_1" class="button2">slow ></button></p>
<p><button id="button3" class="button2">right >>></button></p>
</div>
<div class="content3">
<p><button id="button4" class="button1">reverse</button></p>
</div>
<script>
var gateway = 'ws://'+ window.location.hostname + (window.location.port ? ":" + window.location.port : '') + '/ws';
var websocket;
window.addEventListener('load', onLoad);
function initWebSocket() {
console.log('Trying to open a WebSocket connection...');
websocket = new WebSocket(gateway);
websocket.onopen = onOpen;
websocket.onclose = onClose;
websocket.onmessage = onMessage; // <-- add this line
}
function onOpen(event) {
console.log('Connection opened');
}
function onClose(event) {
console.log('Connection closed');
setTimeout(initWebSocket, 2000);
}
function onMessage(event) {
var state;
if (event.data == "1"){
state = "ON";
}
else{
state = "OFF";
}
document.getElementById('state').innerHTML = state;
}
function onLoad(event) {
initWebSocket();
initButton();
initButton2();
initButton2_1();
initButton3();
initButton3_1();
initButton4();
}
function initButton() {
//document.getElementById('button').addEventListener('click', toggle);
document.getElementById('button').addEventListener('touchstart', forward, false);
document.getElementById('button').addEventListener('touchend', stopper, false);
}
function forward(){
websocket.send('forward');
}
function initButton2() {
document.getElementById('button2').addEventListener('touchstart', left, false);
document.getElementById('button2').addEventListener('touchend', stopper, false);
}
function left(){
websocket.send('left');
}
function initButton2_1() {
document.getElementById('button2_1').addEventListener('touchstart', left_slow, false);
document.getElementById('button2_1').addEventListener('touchend', stopper, false);
}
function left_slow(){
websocket.send('left_slow');
}
function initButton3() {
document.getElementById('button3').addEventListener('touchstart', right, false);
document.getElementById('button3').addEventListener('touchend', stopper, false);
}
function right(){
websocket.send('right');
}
function initButton3_1() {
document.getElementById('button3_1').addEventListener('touchstart', right_slow, false);
document.getElementById('button3_1').addEventListener('touchend', stopper, false);
}
function right_slow(){
websocket.send('right_slow');
}
function initButton4() {
document.getElementById('button4').addEventListener('touchstart', reverse, false);
document.getElementById('button4').addEventListener('touchend', stopper, false);
}
function reverse(){
websocket.send('reverse');
}
function stopper(){
websocket.send('stop');
}
</script>
</body>
</html>
)rawliteral";
void notifyClients() {
ws.textAll(String(ledState));
}
void handleWebSocketMessage(void *arg, uint8_t *data, size_t len) { // обрабатываем получаемые сообщения
AwsFrameInfo *info = (AwsFrameInfo*)arg;
if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) {
data[len] = 0;
if (strcmp((char*)data, "forward") == 0) {
ledState = !ledState;
Serial.println("Forward"); // "Вперед"
state = "Forward";
ledcWrite(pwmChannel, 0); //0 - максимум оборотов
ledcWrite(pwmChannel2, 0); //0 - максимум оборотов
digitalWrite(motor1Pin1, LOW);
digitalWrite(motor1Pin2, HIGH);
digitalWrite(motor2Pin1, LOW);
digitalWrite(motor2Pin2, HIGH);
//notifyClients();
}
else if (strcmp((char*)data, "left") == 0) {
ledState = !ledState;
Serial.println("Left"); // "Влево"
state = "Left";
ledcWrite(pwmChannel, 255);
ledcWrite(pwmChannel2, 0);
digitalWrite(motor1Pin1, HIGH);
digitalWrite(motor1Pin2, LOW);
digitalWrite(motor2Pin1, LOW);
digitalWrite(motor2Pin2, HIGH);
//notifyClients();
}
else if (strcmp((char*)data, "left_slow") == 0) {
ledState = !ledState;
Serial.println("LeftSlow"); // "Влево медленно"
state = "LeftSlow";
ledcWrite(pwmChannel, 155);
ledcWrite(pwmChannel2, 100);
digitalWrite(motor1Pin1, HIGH);
digitalWrite(motor1Pin2, LOW);
digitalWrite(motor2Pin1, LOW);
digitalWrite(motor2Pin2, HIGH);
//notifyClients();
}
else if (strcmp((char*)data, "right") == 0) {
ledState = !ledState;
Serial.println("Right"); // "Вправо"
state = "Right";
ledcWrite(pwmChannel, 0);
ledcWrite(pwmChannel2, 255);
digitalWrite(motor1Pin1, LOW);
digitalWrite(motor1Pin2, HIGH);
digitalWrite(motor2Pin1, HIGH);
digitalWrite(motor2Pin2, LOW);
//notifyClients();
}
else if (strcmp((char*)data, "right_slow") == 0) {
ledState = !ledState;
Serial.println("RightSlow"); // "Вправо медленно"
state = "RightSlow";
ledcWrite(pwmChannel, 100);
ledcWrite(pwmChannel2, 155);
digitalWrite(motor1Pin1, LOW);
digitalWrite(motor1Pin2, HIGH);
digitalWrite(motor2Pin1, HIGH);
digitalWrite(motor2Pin2, LOW);
//notifyClients();
}
else if (strcmp((char*)data, "reverse") == 0) {
ledState = !ledState;
Serial.println("Reverse"); // "Назад"
state = "Reverse";
ledcWrite(pwmChannel, 255); //255 - максимум оборотов
ledcWrite(pwmChannel2, 255); //255 - максимум оборотов
digitalWrite(motor1Pin1, HIGH);
digitalWrite(motor1Pin2, LOW);
digitalWrite(motor2Pin1, HIGH);
digitalWrite(motor2Pin2, LOW);
//notifyClients();
}
else if (strcmp((char*)data, "stop") == 0) {
ledState = !ledState;
Serial.println("Stop"); // "Стоп"
state = "Stop";
ledcWrite(pwmChannel, 0);
ledcWrite(pwmChannel2, 0);
digitalWrite(motor1Pin1, LOW);
digitalWrite(motor1Pin2, LOW);
digitalWrite(motor2Pin1, LOW);
digitalWrite(motor2Pin2, LOW);
//notifyClients();
}
}
}
void onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type,
void *arg, uint8_t *data, size_t len) {
switch (type) {
case WS_EVT_CONNECT:
Serial.printf("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str());
break;
case WS_EVT_DISCONNECT:
Serial.printf("WebSocket client #%u disconnected\n", client->id());
break;
case WS_EVT_DATA:
handleWebSocketMessage(arg, data, len);
break;
case WS_EVT_PONG:
case WS_EVT_ERROR:
break;
}
}
void initWebSocket() {
ws.onEvent(onEvent);
server.addHandler(&ws);
}
String processor(const String& var){
Serial.println(var);
if(var == "STATE"){
if (ledState){
return "ON";
}
else{
return "OFF";
}
}
}
//-------------------------------------------------------------------------------------------------------
void setup() {
Serial.begin(115200);
// переключаем контакты моторов в режим «OUTPUT»:
pinMode(motor1Pin1, OUTPUT);
pinMode(motor1Pin2, OUTPUT);
pinMode(motor2Pin1, OUTPUT);
pinMode(motor2Pin2, OUTPUT);
// подключаем контакты оптических датчиков к пину, в режим «INPUT»:
pinMode (SensorPin1, INPUT);
pinMode (SensorPin2, INPUT);
//подключаем реакцию на прерывания - к пинам датчиков:
// attachInterrupt(SensorPin1, sensor_impulse, LOW);
// attachInterrupt(SensorPin2, sensor_impulse2, LOW);
// задаем настройки ШИМ-канала каждого из 2 двигателей:
ledcSetup(pwmChannel, freq, resolution); // первый двигатель
ledcSetup(pwmChannel2, freq2, resolution2); // второй двигатель
// подключаем ШИМ-канал, к контактам для управления скоростью вращения каждого из 2 моторов:
ledcAttachPin(motor1Pin1, pwmChannel); // первый двигатель
ledcAttachPin(motor2Pin1, pwmChannel2); // второй двигатель
// подаем на контакты ШИМ-сигнал с коэффициентом заполнения «0»:
ledcWrite(pwmChannel, dutyCycle);
ledcWrite(pwmChannel2, dutyCycle2);
// Настраиваем статический IP-адрес сервера:
if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
Serial.println("STA Failed to configure"); // "Не удалось задать статический IP-адрес"
}
// Connect to Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
// Print ESP Local IP Address
Serial.println(WiFi.localIP());
initWebSocket();
// Route for root / web page
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html, processor);
});
// Start server
server.begin();
}// END SETUP
void loop(){
ws.cleanupClients();
} // END LOOP
Connecting to WiFi..
192.168.1.240
WebSocket client #1 connected from 192.168.1.216
WebSocket client #2 connected from 192.168.1.1
WebSocket client #3 connected from 192.168.1.1
WebSocket client #4 connected from 192.168.1.1
внутри работает на порту 8000
снаружи виден на портах 8080, 9000 и т.д.
PS. При нештатном отключении сети (ребуте ESP-шки) браузер почему-то событие onClose не генерирует... Не знаю, что за хрень. Жаваскриптом раз в год занимаюсь, тратить на него время не буду, пока стимула не будет )) Порты пробрасываются, а это единственное что меня тут заинтересовало.
Потому что в этом случае разъединение по просьбе еспшки не происходит и клиент должен определять факт обрыва связи по таймауту. Имеет смысл посмотреть что браузер пишет в отладке.
Почему никто из заинтересовавшихся не включил отладку, по крайней мере была бы понятна причина потребовавшая "косметических" изменений.
Я уже прочитал, что из JS Websocket API пинг-понг недоступен и, возможно, просто в нём нереализован. Т.е. рисовать его нужно самому, а это уже выходит за рамки расследования "што там с портами". Браузер ничего не пишет. Просто висит и ждет входящих фреймов.
Хотя, конечно, API странное. Всякое бывает по роутингу и почему канал при этом не контролируется - загадка...
Потому что в этом случае разъединение по просьбе еспшки не происходит и клиент должен определять факт обрыва связи по таймауту. Имеет смысл посмотреть что браузер пишет в отладке.
Почему никто из заинтересовавшихся не включил отладку, по крайней мере была бы понятна причина потребовавшая "косметических" изменений.
включал, нет там никакой информации, коннект-дисконнект и пожалуй всё, забыл, один раз немного высыпало, но повторить аналогичное сообщение не получилось, а скопировать в буфер что-то не догадался
если бы у меня был esp32 проверил бы на реальном, а так, чем мог, пробросил с 85 на 80 nmap сказал, что с UDP всё зашибись
Очевидно, что проблема не в этом.
если бы у меня был esp32 проверил бы на реальном, а так, чем мог, пробросил с 85 на 80 nmap сказал, что с UDP всё зашибись
Очевидно, что проблема не в этом.
Хм, а может и в этом. ТС, скорее всего, tcp «пробрасывал», а как же udp? Может железки по нему общаются?
Хм, а может и в этом. ТС, скорее всего, tcp «пробрасывал», а как же udp? Может железки по нему общаются?
Меня это утверждение пугает :)
если бы у меня был esp32 проверил бы на реальном, а так, чем мог, пробросил с 85 на 80 nmap сказал, что с UDP всё зашибись
Очевидно, что проблема не в этом.
Хм, а может и в этом. ТС, скорее всего, tcp «пробрасывал», а как же udp? Может железки по нему общаются?
я пробросил и TCP и UDP, реальной железки esp32 нет, роутер тплинк но чуть покруче, ось OWRT, по умолчанию вэбморда предлагала пробросить 85 на 85
Хм, а может и в этом. ТС, скорее всего, tcp «пробрасывал», а как же udp? Может железки по нему общаются?
Меня это утверждение пугает :)
Почему? Вы что-то знаете и не говорите?)
если бы у меня был esp32 проверил бы на реальном, а так, чем мог, пробросил с 85 на 80 nmap сказал, что с UDP всё зашибись
Очевидно, что проблема не в этом.
Хм, а может и в этом. ТС, скорее всего, tcp «пробрасывал», а как же udp? Может железки по нему общаются?
я пробросил и TCP и UDP, реальной железки esp32 нет, роутер тплинк но чуть покруче, ось OWRT, по умолчанию вэбморда предлагала пробросить 85 на 85
Оно и понятно, по умолчанию так и должно быть. Но wrt очень крутая прошивка, что там в родной происходит - не известно.
TP-Link TL-WR741N, как и любой другой, спокойно даёт пробросить порт 80. Вебсокет использует tcp. Проброс портов в родной прошивке tp-link работает точно так же, как и в open/dd/ху*-wrt. Дело, скорее всего, не в этом.
TP-Link TL-WR741N, как и любой другой, спокойно даёт пробросить порт 80. Вебсокет использует tcp. Проброс портов в родной прошивке tp-link работает точно так же, как и в open/dd/ху*-wrt. Дело, скорее всего, не в этом.
Конечно вебсокет работает по tcp. udp никоим боком. Просто челу "апоговорить" похоже. В любом случае не нужно его на 80-й порт вешать. То что TP-Link должен иметь возможность настраиватся на проброс 80 как бы ожидаемо, иначе дома и апачу не развернеш с домашним сайтом.
//Дело, скорее всего, не в этом.
да.
Ты читать не умеешь ? Где я написал, что не доволен !? Не нужно читать между строк.
Здесь!
Вообще все негативные отзывы от этой либе в теме - только от тебя. И про проблему больших данных и ссылки на список ошибок. Меня больше возмутило обобщение проблем аж до асинхронного веба. Ну кривая либа (возможно, ты ж о ней такое пишеш), ну некоторые не поняли как ее дергать. Тоже мне новости. Обобщать с ссылкой на "что у огромной массы людей асинхронный веб вызывает стойкую аллергию" не стоит, твои пацаны на районе не тянут просто ;)
Кстати ты смысл своего первого предложения на русский не переведешь ? Что ты хотел сказать ? Что ТС не использует , как ты выразился "кривую либу тупого автора" ? Или что ? Так , на всякий случай, я говорил именно о библиотеке
И я о библиотеке и ее авторе, о чем жеж еще, все ты понял.
И еще раз повторю, проблема этой библиотеки на ESP32 в том, что в колбэках нельзо долго оставаться. С ними нужно работать практически как с прерываниями, потому как они из другого потока.
У тя каша в башке, потому то прерывания, то как бы прерывания то другой поток. Ты похоже имел в виду что луп и калбеки в разных потоках и требуют синхронизации... Та неважно, забей, то слишком сложно.
Кстати можно или нельзя долго оставаться - это совсем не к свойствам калбека или потока, это к качеству либы. И судя по твоим словам, подчеркиваю, именно по твоим словам!!!, не отнекивайся и стрелки не переводи, либа таки действительно кривая.
Потому как таких страстей-мордастей протокол вебсокета вобще не требует. Как и ТСР в общем. Вебсокет тупо на нем построен и если есть проблема приема больших данных - см. стек ТСР. За некоторым исключением. Как чел, реализовавший себе этот протокол, отмечу, что вопросу длинны данных во фрейме (это терменология спеки на вебсокет) в протоколе особое внимание. Длина поляв котором эта самая длина данных передается переменная и применима для данных до 2^64 байт. А при коротких данных, до 125, свой формат, компактный. Уже из этого следует что проблемы принципиальной нет. А что там автор наваял, поддержал ли все кейсы или нет - на его совести. Я писал так.
Но насколько верно - я даже не знаю т.к. больших данных мне не попадалось. Ну вот так... Не тестил.
Далее. Эта самая длина, и прочая пурга из хедера - в начале фрейма, т.е. в одном tcp пакете с первыми байтами данных. Очевидно при длине данных до 125 у нас всегда все принято на момент парсинга хедера. И попытка получить данные сразу после парсинга будет успешная. А для данных почти 2^64 или около того - придется долго ждать пока приедут, стек ТСР их сложит и т.д. Как это согласовать с быстрой обработкой калбека - ХЗ, думал ли автор о проблеме - ХЗ, сталкивался ли ты с этим - ХЗ. Но похоже что либа не для этого случая..
Далее, обратил внимание, ТС хочет машинкой рулить. А это как бы значить, что клиент у вебсокета один. Тогда спрашивается, нахрена этот цирк с потоками который приводит к проблемам? И ситуация когда клиент один (реже 2-3 но не много) очень типичная для МК. А автор либы взял типовую архитектуру сервера, и каждому клиенту поток забецал. При скудных ресурсах создал доп проблемы. Это тоже не в плюс либе...
Продолжу тут, форум тупит. Так вот, накосячить в либе есть где. И с большими данными тоже. И ее архитектура, многопоточность, калбеки вызывает сомнения. Но это не повод писать о проблемах асинхронного веба и протокола вебсокет вобще. Свет клином на этой либе не сошолся. И тем более вопросы по либе к теме форума не относятся. У ТС в локалке работает. Причем тут либа. Разнесет порты, настроит проброс и заработает. Не смущайте чела почем зря.
Продолжу тут, форум тупит. Так вот, накосячить в либе есть где. И с большими данными тоже. И ее архитектура, многопоточность, калбеки вызывает сомнения. Но это не повод писать о проблемах асинхронного веба и протокола вебсокет вобще. Свет клином на этой либе не сошолся. И тем более вопросы по либе к теме форума не относятся. У ТС в локалке работает. Причем тут либа. Разнесет порты, настроит проброс и заработает. Не смущайте чела почем зря.
Не буду тут растекаться , как это делаешь ты. Придирки к словам , которые ты таскаешь из контекста - хрень ни о чем.
По теме. Дело в том, что скорость потока данных в локалке и из-вне разная. А это приводит к тому, что одни и те же обработки работают разное время. Я не буду тут жевать по буквам почему и как. НО любая асинхронная библиотека первым делом обращает внимание на то, что обработки выполняются в другом потоке нежели основной цикл. Как это достигнуто, с использованием прерываний, потоками, другими способами - значения не имеет. Но они должны быть короткие и правильно оперировать данными.
ЗЫ Ты когда пишешь так многостранично, ты думай зачем ты это делаешь. Я твое "полотенце" не читал. И не буду. Много есть на то причин. Основная - не интересно. Ты все равно ничего умного в таком количестве сказать не мог :)
ЗЫ Ты когда пишешь так многостранично, ты думай зачем ты это делаешь. Я твое "полотенце" не читал. И не буду.
И это тот кто обвинял меня в том что я не читаю сообщений! Ты вообще помнишь что пишеш тремя постами ранее?))) То то ты все не в попад отвечаешь, да порешь чушь. То прерывания, то потоки. Оно так в башке хаос и останется, если не читать. Вот и здесь, в трех предложениях столько ахинеи нанес..
Дело в том, что скорость потока данных в локалке и из-вне разная. А это приводит к тому, что одни и те же обработки работают разное время. Я не буду тут жевать по буквам почему и как. НО любая асинхронная библиотека первым делом обращает внимание на то, что обработки выполняются в другом потоке нежели основной цикл. Как это достигнуто, с использованием прерываний, потоками, другими способами - значения не имеет. Но они должны быть короткие и правильно оперировать данными.
Библиотека у него обращает внимание)) Та отдельные потоки для клиента как раз создают чтоб они работали независимо и тормоза одного не влияли на остальных. Это оправдано для ПК и как часто бывает не оправдано на МК. В том их отличие от обработчика прерывания в плане длительности исполнения. Ну ты ж не читаешь, ходи дальше дремучим. Считай твой культпросвет закончен, дальше я только время на тупицу потеряю. Если за шесть лет на форуме не понимаешь разницу между потоком и прерыванием - безнадежен.
Я пишу по теме. Ты фонтанируешь потоком мысли и придирками.
Для меня русский не родной :) Так что утрись :)
Я вас обеих тереть буду. :)
Я вас обеих тереть буду. :)
Три ! Или даже ЧЕТЫРЕ !
Я буду кричать что притесняют нацменьшинства :) И мысли у меня не отбирай. Жить с "одной мыслью" скучно :(
Я вас обеих тереть буду. :)
Всё, что до этого было, я, естественно, не трону, пусь вам стыдно будет. Я просто к тому, что давайте цивилизованно вести дискуссию, без всяких "крысоухих змей" и прочего. :)
Меня в этой теме потрите. Писал же что не сильно разбираюсь, следовательно предполагал. А на меня чан г#вна от «не с кем поговорить». (
Я вас обеих тереть буду. :)
Всё, что до этого было, я, естественно, не трону, пусь вам стыдно будет. Я просто к тому, что давайте цивилизованно вести дискуссию, без всяких "крысоухих змей" и прочего. :)
А я и вел цивилизованно, пока не набежали "двое из ларца" и не стали умные советы бредом называть
Ой сколько нопесале.... :-)))
Не имел возможности заходить-тупо был загружен работой. Зашел-а тут такоооеее... :-)
Ок, давайте так. Выложу код проекта сюда (мне не жалко). Неплохой пульт управления получился для машинки-со смартфона. Может кто скажет чего умного...
Вот как мне его заставить видеться и работать извне? Видится-но даже кнопки не жмакаются.
а порт более 1024 задать можешь?
а порт более 1024 задать можешь?
Не подкола ради-пробовал разные...Но не то, что ты говоришь... Не работало. А что это даст?
задвоение сообщения запостилось.
а порт более 1024 задать можешь?
Не подкола ради-пробовал разные...Но не то, что ты говоришь... Не работало. А что это даст?
мыслей нет, но выше 1024 это пользовательские порты, может в этом проблема
Ок, сейчас залью и протестю. Отпишусь.
UPD: протестил. Залил 1025 порт. Так же-видится отлично, но не работает.
интернет от какого сотового оператора?
интернет от какого сотового оператора?
Билайн-Москва.
мыслей нет, но выше 1024 это пользовательские порты, может в этом проблема
Это ни о чем не говорит. Относитесь к портам и их пробросу проще. Это я вам как цисковод с дипломами говорю ;)
мыслей нет, но выше 1024 это пользовательские порты, может в этом проблема
Это ни о чем не говорит. Относитесь к портам и их пробросу проще. Это я вам как цисковод с дипломами говорю ;)
начинать анализ надо с того, что открыть страничку с компьютера и посмотреть исходный код страницы, мне так кажется, если в коде косяков нет, то на локальной сети (не вайфай) открыть простейший сервер www и на него сделать проброс, если эта связка заработает, останется только бридж на вайфай... но проблемы могут быть и с MTU
Зачем все так усложнять ? Не в этом дело. Почему мы всегда пытаемся искать ошибки у других. Нужно искать у себя. Ошибка в коде ESP, она же сваливает в ошибку, значит кривой код. Если бы было все нормально, то с какого фига эксепшены возникали бы ? Есп это вам не мега328, есп даже на ноль делить не даст :)
Зачем все так усложнять ? Не в этом дело. Почему мы всегда пытаемся искать ошибки у других. Нужно искать у себя. Ошибка в коде ESP, она же сваливает в ошибку, значит кривой код. Если бы было все нормально, то с какого фига эксепшены возникали бы ? Есп это вам не мега328, есп даже на ноль делить не даст :)
он же говорит, что в локалке работает, проблем нет
Зачем все так усложнять ? Не в этом дело. Почему мы всегда пытаемся искать ошибки у других. Нужно искать у себя. Ошибка в коде ESP, она же сваливает в ошибку, значит кривой код. Если бы было все нормально, то с какого фига эксепшены возникали бы ? Есп это вам не мега328, есп даже на ноль делить не даст :)
он же говорит, что в локалке работает, проблем нет
Еще раз . Внимательно. ЕСП сваливается с ошибкой. Кто сваливается роутер ? Провайдер ? Так почему мы пытаемся роутер крутить ? Ну смешно :)
Ок, сейчас залью и протестю. Отпишусь.
UPD: протестил. Залил 1025 порт. Так же-видится отлично, но не работает.
А в строке 241 не забыл указать этот порт, типа
var gateway = `ws:
//${window.location.hostname}/ws:1025`;
?Ок, сейчас залью и протестю. Отпишусь.
UPD: протестил. Залил 1025 порт. Так же-видится отлично, но не работает.
А в строке 241 не забыл указать этот порт, типа
var gateway = `ws:
//${window.location.hostname}/ws:1025`;
?Протестил-не хочет...Та же история-видится снаружи,но не работает. В локалке всё ок.
Включите уже лог. Запишите его для удачного подключения и для неудачного. Проще будет "гадать на кофейной гуще".
Включить системный лог для ESP
Выложу код проекта сюда (мне не жалко). Неплохой пульт управления получился для машинки-со смартфона. Может кто скажет чего умного...
а что сказать, если ОНО даже не компилируется, хотел по быстрому проверить, получил ESP32 и время есть )))
Замаркировал, скомпилировал, страничка отображается, а где индикация?
Код не рабочий даже без проброса портов )))
На зарезервированный. То бишь: я выяснил MAC адрес своей esp32 и связал ее MAC с ip адресом (в моем случае, внутренний адрес от роутера выдан такой: 192.168.0.106) в настройках роутера.
То есть: теперь при любом коннекте esp32 к роутеру- он ей выдает этот ip.
Ну и опять же: все видится снаружи, то бишь всё вроде работает. Но через задницу :-))))
и не надо выяснять МАС, надо просто назначить статический IP на девайс, добавить:
Залил скетч из примеров ESP32 для вэбсокета!
ДА! Через проброшенный порт не работает (OpenWrt, TP-LINK 842ND)
Пробрасываю порт 8080 на 80, а вот если пробрасывать 80 на 80 порт, то работает
На кроссоверных портах не устанавливается websocket соединение, так получается, осталось понять почему
Один и тот же код для проверки использую и для ESP8266 и для ESP32, только библиотеки разные...
Проверил сделав проброс с 8080 на 80 на ESP32 и, работает...скетч правда websocket не использует
Беру еще один пример. там где WS отрабатывает в обе стороны и, через проброшенный порт не работает ни на ESP8266 ни на ESP32, мало того и сервер на порту отличном от 80 не работает на обоих девайсах...
ДА УЖ с этим вэбсокетом всё не так просто
А вот так?
Так работает )))
Попробую 8000 порт, но уже завтра
вот кстати, приходил к мысли, что вэбсокет отвечает на 80 порту...
На любом назначенном порту он отвечает.
На любом назначенном порту он отвечает.
так оно не назначено было видимо!
Проверил и на esp8266 и на ESP32 в любых комбинациях портов работает, еще бы кнопку прилепить и индикатор, что от клиента до сервера и обратно отрабатывает...
Выходит дело было не в бобине? )))
PS Значит скетчи из инета с примерами вэбсокетов кривые, надо же а они информацию даже продают...
Не в бобине, а в непонимании принципа работы протокола. Скетчей "из интернета" я не видел. Может и кривые, а может и просто заточены под конкретную задачу.
Кнопки мне неинтересно приделывать, а вот демо клиентской части поустойчивей я сделал для тестов:
Заменил кусок, работает, сейчас сервер работает на 8000 порту а проброс снаружи делаю с порта 8080, сейчас еще пару правил в роутере добавлю, посмотрю
тестирую на 12 клиентах, я правильно понимаю, если обмен завис более чем на 2 секунды сокет переоткрывается?
Если клиент отвалился (штатно или нет), то следующая попытка переподключения будет произведена через 2 секунды.
Если клиент отвалился (штатно или нет), то следующая попытка переподключения будет произведена через 2 секунды.
прекрасная надёжность получается, напрашивается дополнить скетч подсчётом числа переподключений...
Для тестовых испытаний
Даже столь косметические изменения программы делают её работоспособной для доступа с наружней сети
Код конечно совсем кривой, ТС, ты бы поправил:
Не знаю, зачем реконнекты считать, но для интересу...
PS. При нештатном отключении сети (ребуте ESP-шки) браузер почему-то событие onClose не генерирует... Не знаю, что за хрень. Жаваскриптом раз в год занимаюсь, тратить на него время не буду, пока стимула не будет )) Порты пробрасываются, а это единственное что меня тут заинтересовало.
Потому что в этом случае разъединение по просьбе еспшки не происходит и клиент должен определять факт обрыва связи по таймауту. Имеет смысл посмотреть что браузер пишет в отладке.
Почему никто из заинтересовавшихся не включил отладку, по крайней мере была бы понятна причина потребовавшая "косметических" изменений.
Я уже прочитал, что из JS Websocket API пинг-понг недоступен и, возможно, просто в нём нереализован. Т.е. рисовать его нужно самому, а это уже выходит за рамки расследования "што там с портами". Браузер ничего не пишет. Просто висит и ждет входящих фреймов.
Хотя, конечно, API странное. Всякое бывает по роутингу и почему канал при этом не контролируется - загадка...
Потому что в этом случае разъединение по просьбе еспшки не происходит и клиент должен определять факт обрыва связи по таймауту. Имеет смысл посмотреть что браузер пишет в отладке.
Почему никто из заинтересовавшихся не включил отладку, по крайней мере была бы понятна причина потребовавшая "косметических" изменений.
включал, нет там никакой информации, коннект-дисконнект и пожалуй всё, забыл, один раз немного высыпало, но повторить аналогичное сообщение не получилось, а скопировать в буфер что-то не догадался