Web сервер на несколько одновременных соединений

vde69
Offline
Зарегистрирован: 10.01.2016

Наконец доделал (в свободное время) сервер на esp8266, примерно выглядит так

WiFiServer server(80);
WiFiClient client;					  // подразумеваем, что у нас будет только одна сесия

void loop() {
	LoopReadUart();

	if (client)	{
		if (time_pause(time_loop_new, millis()) > 10000) {
			// держим не более 10 сек
			client.stop();
			clear_param_wifi();
		}
	}

	if (!client) {
		// попытка создание клиентской сессии
		client = server.available();
		if (client)	{
			time_loop_new = millis();
		}
	}

	if (client)	{
		LoopReadWiFi();
	}
}

Но он работает только для одной сессии, в инете почти все примеры сделаны аналогичны. 

Нужно сделать на несколько сессий, как пример есть например вот  ссылка на https://github.com/esp8266/Arduino/issues/307 примерчик, но меня смущает статическое выделение памяти сразу на максимум сокетов. С другой стороны динамическое выделение может привести к сильной сегментации (по сколько куски большие на буфер данных должны выделятся) памяти и периодическому ребуту. 

Если у кого есть примеры реализации мультиклиентского сервера подтолкните :)

ну и второй вопрос - как сделать авторизацию, в теории я знаю пару способов, но хотелось-бы конкретику глянуть, да я понимаю, что на клиенте нужно хранить или куку или параметр сесии (и это у меня уже реализовано) а вот как сделать относительно безопасно передачу этого значения с сервера на клиент? и какой по составу он должен быть?

 

 

rkit
Offline
Зарегистрирован: 23.11.2016

espasyncwebserver + tls

Logik
Offline
Зарегистрирован: 05.08.2014

//Если у кого есть примеры реализации мультиклиентского сервера подтолкните :)

Подталкиваю. Не делай так.ESP и с одним клиентом дышет еле. Если светить в внешний мир портом, то большой разницы сколько клиентов поддержать нету. Нехватит по любому. А в локалке и один клиент достаточен.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

32 еспешка нормально дышит и решение есть, но не такое короткое как в примере. 

Logik
Offline
Зарегистрирован: 05.08.2014

Она конечно помощней, но и для нее вроде тоже пишут до 5 подключений. Хоть я лично не пробовал 32-ю.

vde69
Offline
Зарегистрирован: 10.01.2016

сделал на 5 подключений, любое выше 5 подключений выдает страницу 503, правда пока не смог проверить на превышение, реально проверял только на 3х параллельных устройствах.

работает вообще шикарно.

осталось авторизацию добавить и будет мне счастье :)

 

пока вот так 

void loop() {
	// обработчик UART
	LoopReadUart();

	uint8_t i;
	// сначала закроем все просроченные сессии
	for(i = 0; i < MAX_SRV_CLIENTS; i++){
		if ( clients[i].client && !clients[i].client.available()) {
			if (time_pause(clients[i].p.time_loop_new, millis()) > 10000) {
				// держим не более 10 сек
				clients[i].client.stop();
				clear_param(&(clients[i].p));
			}
		}
	}

	// попытка создание новых клиентских сессии
	if (server.hasClient()){
		for(i = 0; i < MAX_SRV_CLIENTS; i++){
			if (!clients[i].client){
				clients[i].client = server.available();
				continue;
			}
		}
		//нет свободных соединений
		WiFiClient serverClient = server.available();
		out_503(&serverClient);
		while (serverClient.available()) { serverClient.read(); }
		serverClient.stop();
	}

	// для каждого активного клиента запускаем обработчик цикла
	for(i = 0; i < MAX_SRV_CLIENTS; i++){
		if ( clients[i].client ) {
			LoopReadWiFi(&(clients[i]));
		}
	}
}

 

Logik
Offline
Зарегистрирован: 05.08.2014

А MAX_SRV_CLIENTS у тя наверно 5.

//работает вообще шикарно.

угу. Пока пустой. Там куча общая и для ТСР стека и для приложения. Просекаеш? Добавь где   client.print("Free RAM="); client.print(ESP.getFreeHeap()); и следи за процессом. 

Кстати, че будет выдавать эта getFreeHeap() - пиши сюда, всем интересно.

 

 

vde69
Offline
Зарегистрирован: 10.01.2016

обязательно отпишусь, но позже...

vde69
Offline
Зарегистрирован: 10.01.2016

немного поигрался с 2х паралельных сессий

вывод памяти происходит только при отправки данных сервером на клиент

 

15:41:24.877 -> ..
15:41:24.877 -> 
15:41:24.877 -> WiFi connected
15:41:24.877 -> Server started
15:41:24.877 -> 192.168.10.101
15:41:32.490 -> Free RAM=45608
15:41:37.530 -> Free RAM=45104
15:41:42.530 -> Free RAM=45104
15:41:47.559 -> Free RAM=45104
15:41:52.575 -> Free RAM=44992
15:41:57.597 -> Free RAM=45104
15:42:02.621 -> Free RAM=44720
15:42:07.535 -> Free RAM=44528
15:42:12.496 -> Free RAM=44464
15:42:13.106 -> Free RAM=44272
15:42:13.140 -> Free RAM=44272
15:42:17.507 -> Free RAM=44464
15:42:18.113 -> Free RAM=44272
15:42:22.508 -> Free RAM=44464
15:42:23.152 -> Free RAM=44272
15:42:27.451 -> Free RAM=44080
15:42:27.485 -> Free RAM=44272
15:42:32.449 -> Free RAM=44080
15:42:32.483 -> Free RAM=44272
15:42:37.479 -> Free RAM=44080
15:42:37.514 -> Free RAM=44272
15:42:42.489 -> Free RAM=44080
15:42:42.524 -> Free RAM=42736
15:42:47.488 -> Free RAM=44080
15:42:47.488 -> Free RAM=44160
15:42:52.479 -> Free RAM=44080
15:42:52.513 -> Free RAM=44080
15:42:57.481 -> Free RAM=44080
15:42:57.515 -> Free RAM=44080
15:43:02.488 -> Free RAM=44080
15:43:02.523 -> Free RAM=43408
15:43:07.496 -> Free RAM=43560
15:43:07.496 -> Free RAM=42736
15:43:12.523 -> Free RAM=43448
15:43:12.523 -> Free RAM=42736
15:43:17.530 -> Free RAM=43520
15:43:17.530 -> Free RAM=42736
15:43:18.879 -> Free RAM=43888
15:43:22.379 -> Free RAM=43888
15:43:22.514 -> Free RAM=44080
15:43:23.759 -> Free RAM=43888
15:43:26.855 -> Free RAM=43888
15:43:27.529 -> Free RAM=44080
15:43:31.842 -> Free RAM=43888
15:43:32.515 -> Free RAM=44080
15:43:35.706 -> Free RAM=43776
15:43:36.856 -> Free RAM=43576
15:43:38.616 -> Free RAM=43768
15:43:40.762 -> Free RAM=43768
15:43:41.849 -> Free RAM=43576
15:43:45.362 -> Free RAM=43152
15:43:46.853 -> Free RAM=43576
15:43:49.316 -> Free RAM=43576
15:43:50.364 -> Free RAM=43768
15:43:54.326 -> Free RAM=43576
15:43:55.348 -> Free RAM=43960
15:44:00.352 -> Free RAM=44016
15:44:05.353 -> Free RAM=44016
15:44:09.316 -> Free RAM=43824
15:44:10.359 -> Free RAM=44016
15:44:14.334 -> Free RAM=43824
15:44:15.344 -> Free RAM=44016
15:44:19.369 -> Free RAM=43824
15:44:20.342 -> Free RAM=44016
15:44:25.346 -> Free RAM=44016
15:44:30.380 -> Free RAM=44016
15:45:12.864 -> Free RAM=43576
15:45:17.856 -> Free RAM=43576
15:45:22.885 -> Free RAM=43960
....
....
15:47:13.080 -> Free RAM=44616
15:47:19.067 -> Free RAM=45112
15:47:25.056 -> Free RAM=45112
15:47:31.071 -> Free RAM=45112
 
вроде все хорошо
 
brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Logik пишет:

Она конечно помощней, но и для нее вроде тоже пишут до 5 подключений. Хоть я лично не пробовал 32-ю.

Это ограничение ее как точки доступа. Но ее ресурсы естественно не бесконечны.

Logik
Offline
Зарегистрирован: 05.08.2014

vde69 пишет:

немного поигрался с 2х паралельных сессий

вывод памяти происходит только при отправки данных сервером на клиент

 

15:47:31.071 -> Free RAM=45112
 
вроде все хорошо
 

Давай разницу при одном клиенте и при двух, трех одновременных .. 

У меня щас Free RAM=26040Б;. При одном клиенте. И тоже скачет- туда сюда на пару КБ. В моем софте есть таблица измерение на 12КБ, лог на 5КБ, sntp , OneWire, обвязка на 3 датчика ds18b20, еще чего по мелочам ... По наблюденям падает прога когда Free RAM к 20КБ подходит. Это экспертная оценка, последнее значение не видно))  И это изредка случается, пару раз в неделю дето. 

Я понемногу "откусывал" ОЗУ от кучи себе, пока не пришел к нестабильности.  Когда Free RAM  выдавало 28-30КБ все было ОК, месяцами работало.

Так понимаю, когда в стеке протокола проблемы, например битые пакеты приходят, или их порядок нарушается, памяти надо  больше. Пакет считаем 1,5КБ плюс по мелочам, это для одного клиента. Не от того ли скачет Free RAM на пару КБ? А если проблема сразу у 5 клиентов? 

 

//вывод памяти происходит только при отправки данных сервером на клиент

Ну все так делают. Вот ща задумался. Можно ведь ловить минимальное значение, каждый проход Loop, выдавать клиенту его при отправки данных сервером.. Ща допилю...

Logik
Offline
Зарегистрирован: 05.08.2014

brokly пишет:

Logik пишет:

Она конечно помощней, но и для нее вроде тоже пишут до 5 подключений. Хоть я лично не пробовал 32-ю.

Это ограничение ее как точки доступа. Но ее ресурсы естественно не бесконечны.

Вот, предлагаю, в этой теме совместными усилиями и прояснить как далеко от реальности до бесконечности )))

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Не, все зависит от структуры сервера и объема данных. Мы этого не знаем. Смысла нет.

vde69
Offline
Зарегистрирован: 10.01.2016

у меня разницы при клиентах почти нет, я сделал по схеме статического массива, туда воткнул все переменные которые привязаны к сессии, 

память скачет примерно в диапазоне 5...6 килобайт 

При этом у меня каждые 5 сек json отрабатывает, получает данные.

на самой есп (а она у меня практически без пинов esp-01s) есть только

обмен по UART с НАНО, именно на НАНО заведены датчики

чтение с файлов из собственного флеша куда и залита страница и отдельно файл с настройками (паролями и т.д.)

и собственно WEB

к такой конфигурации я пришел через простой вывод, лучше 2 контроллера которые будут друг друга мониторить и перегружать по необходимости чем один заткнется... Мониторинг пока не сделал...

 

Плавание кб обьясняестя просто

1. я использую String, он динамит.... в планах есть отказаться от него совсем, у меня остался последняя функция с ним.

2. буферы сервера, они то же динамические, тут все просто - их надо чистить быстрее чем они растут

vde69
Offline
Зарегистрирован: 10.01.2016

вот мой сервер 


<!DOCTYPE html>
<html>
<head>
<link rel='icon' href='data:;base64,='>
<meta charset="UTF-8"/>
<meta http-equiv="Cache-Control" content="no-cache">
<link rel="stylesheet" type="text/css" href="main.css" />
<title>Web Home 259 Page</title>
<script>
// формат: {"t_home_1":{"value":{"data-v":"030"},"status":{"data-st":"OK"}}}
function GetData_H() {
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var vdat = JSON.parse(this.responseText);
if (vdat !== null && typeof vdat === 'object') {
for (var key_id in vdat) {
el = document.getElementById(key_id);
if (el != null) {
var vdat1 = vdat[key_id];
try {for (var key_id1 in vdat1) {
el1 = el.querySelector('p[name='+key_id1+']');
if (el1 != null) {
var vdat2 = vdat1[key_id1];
for (var key_id2 in vdat2) {
el1.setAttribute(key_id2, vdat2[key_id2]);
el.setAttribute(key_id2, vdat2[key_id2]);}
}}}catch (e) {
}}}}}}
request.open('POST', 'ajax_data', true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
request.send(null);
setTimeout('GetData_H()', 5000);}
</script>
</head>
<body onload='GetData_H()'>


<div class="s">
  <div>
  <div class="fon"><div></div></div>
  <div class="time1 set"><div id="t_time_start"><p name="value" data-v="12:30">c: </p></div></div>
  <div class="time1 set"><div id="t_time_end"><p name="value" data-v="22:15">по: </p></div></div>
  <div class="fon"><div></div></div>
  <div class="fon"><div></div></div>
  </div>

  <div>
  <div class="tube red"><div name="left-bottom"></div></div>
  <div class="fon"><div></div></div>
  <div class="fon"><div></div></div>
  <div class="fon"><div></div></div>
  <div class="fon"><div></div></div>
  </div>

  <div>
  <div class="tube blue"><div name="top-bottom"></div></div>
  <div class="fon"><div></div></div>
  <div class="fon"><div></div></div>
  <div class="fon"><div></div></div>
  <div class="fon"><div></div></div>
  </div>
  
  <div>
  <div class="tube blue"><div name="top-bottom"></div></div>
  <div class="fon"><div></div></div>
  <div class="fon"><div></div></div>
  <div class="fon"><div></div></div>
  <div class="fon"><div></div></div>
  </div>

  <div>
  <div class="tube blue"><div name="top-bottom"></div></div>
  <div class="fon"><div></div></div>
  <div class="fon"><div></div></div>
  <div class="fon"><div></div></div>
  <div class="fon"><div></div></div>
  </div>

  <div>
  <div class="tube blue"><div name="top-bottom"></div></div>
  <div class="fon"><div></div></div>
  <div class="fon"><div></div></div>
  <div class="fon"><div></div></div>
  <div class="fon"><div></div></div>
  </div>

  <div>
  <div class="tube blue"><div name="top-bottom"></div></div>
  <div class="fon"><div></div></div>
  <div class="fon"><div></div></div>
  <div class="fon"><div></div></div>
  <div class="fon"><div></div></div>
  </div>

  <div>
  <div class="tube blue"><div name="top-right"></div></div>
  <div class="pump"><div id="m_water"><p name="status"></p></div></div>
  <div class="fon"><div></div></div>
  <div class="fon"><div></div></div>
  <div class="fon"><div></div></div>
  </div>

  <div class="decoration" style="--w:4;--h:1; --l:0; --t:0; "><p>Контроль</p></div>
  <div class="decoration tank" style="--w:3;--h:6; --l:1; --t:2"><p name="value">Колодец: </p><div id="level" name="value"></div></div>

  <div class="set_forms" id="forms_edit" data-f="off" >
	<p name="value">Установка параметра: </p>
	<input type="text" id="forms_edit_i">
	<button type="button" id="forms_edit_ok">OK</button>
	<button type="button" id="forms_edit_close">X</button>
  </div>

  
</div>


<script>
function open_set(el_op) {
	el = document.getElementById('forms_edit');
	if (el != null) { el.setAttribute('data-f','on'); }
	el = document.getElementById('forms_edit_i');
	if (el != null) { el.value=el_op.getAttribute('data-v'); el.name=el_op.id; }
}
function close_set(el_op) {
	el = document.getElementById('forms_edit');
	if (el != null) { el.setAttribute('data-f','off')}
}
function send_set(el_op) {	
	var request = new XMLHttpRequest();
	request.onreadystatechange = function() {
		if (this.readyState == 4 && this.status == 200) {
			var vdat = JSON.parse(this.responseText);
			if (vdat !== null && typeof vdat === 'object' && vdat.set == 'ok') { close_set(el_op); }}}
	el = document.getElementById('forms_edit_i');
	el = '<'+el.name+'='+el.value+';'+localStorage.getItem('crc')+'>\r\n';
	request.open('POST', 'ajax_set_data', true);
	request.setRequestHeader('Content-Type', 'application/xml');
	request.send(el);	
}


function reg_set(el_op, oper) {
	el = document.getElementById(el_op);
	if (el != null) { 
		if (oper == 'open') { 
			el.onclick=function() { open_set(this); return false; } 		
		} else if (oper == 'close') {
			el.onclick=function() { close_set(this); return false; } 		
		} else if (oper == 'send') {
			el.onclick=function() { send_set(this); return false; } 		
		}				
	}
}
reg_set('t_time_start','open');
reg_set('t_time_end','open');
reg_set('forms_edit_ok','send');
reg_set('forms_edit_close','close');
</script>


</table>
</body>
</html>
@charset "windows-1251";
/* CSS Document */

:root {
  --Step: 75px;
  --ColorFon: #ffffff;
}


.s {
	position:relative;
	width:calc(var(--Step) * 5);
	height:calc(var(--Step) * 8);
	top:10px;
	left:10px;
	overflow:hidden;
}


.fon > div {
	float:left;
	overflow:hidden;
	width:var(--Step); 
	height:var(--Step);
}

/* ---------------------------------------------- */

.set_forms {
	overflow:hidden;
    position: absolute;
	width: 100%; 
	height: 100%; 
	z-index: 1000;
	background-color: #99FFCC;	
	visibility: hidden;
}


.set_forms[data-f="on"] {
	visibility: visible
}

.set_forms[data-f="off"] {
	visibility: hidden;
}

.set_forms > div{
	overflow:hidden;
    position: absolute;
	width: 100%; 
	height: 100%; 
	z-index: 1000;
	background-color: #99FFCC;	

/*
	visibility: hidden;
	visibility: visible  margin-right: 10px;
*/	
}

.set_forms > button{
	cursor: pointer;
}
.set_forms #forms_edit_close{
	margin-right: 5px;
	float: right;
}



/* ---------------------------------------------- */

.tank > div {
	--value: 0; 
	
	overflow:hidden;
    position: absolute;
	left:2px;
	top:20px;
	width:calc(100% - 4px); 
	height:calc(100% - 2px); 
	background-color: #B3FFF2;
	background-repeat: no-repeat;
	background-position: left bottom;
	border-top: calc((var(--Step) * var(--h) - 2px) - ((var(--Step) * var(--h) - 2px - 2px) * var(--value) / 100 )) solid var(--ColorFon);
}

/* сюда вставляем все возможные варианты значения заполнения бака data-v */
.tank > div[data-v="100%"] {
	--value: 100;
	background-color: #CC6600;
}
.tank > div[data-v="90%"]  {
	--value: 90; 
	background-color: #FFAA80;
}
.tank > div[data-v="80%"]  {
	--value: 80; 
	background-color: #80AAFF;
}
.tank > div[data-v="70%"]  {--value: 70; }
.tank > div[data-v="60%"]  {--value: 60; }
.tank > div[data-v="50%"]  {--value: 50; }
.tank > div[data-v="40%"]  {--value: 40; }
.tank > div[data-v="30%"]  {--value: 30; }
.tank > div[data-v="20%"]  {--value: 20; }
.tank > div[data-v="10%"]  {
	--value: 10; 
	background-color: #FF0000;
}


.tank p[name=value]{
	margin-left: 5px;
}

.tank p[name=value]:after{
	content: attr(data-v);
}




/* ---------------------------------------------- */

.decoration {
	position: absolute;
	left:calc(var(--Step) * var(--l));
	top:calc(var(--Step) * var(--t));
	float:left;
	overflow:hidden;
	width:calc(var(--Step) * var(--w) - 2px); 
	height:calc(var(--Step) * var(--h) - 2px); 
	border: 1px dashed red;
	z-index: -1;
}

.decoration > p {
    margin-left: 5px;
    margin-top: 5px;
	font-weight: bold;
	color: #283593;
}

/* ---------------------------------------------- */

.tube.red  > div {
	background-image: url(tube_red.png); 
}

.tube.blue > div {
	background-image: url(tube_blue.png); 
}

.tube > div {
	
	--Top: 34px;
	--Bottom: 34px;
	--Left: 34px;
	--Right: 34px;

	float:left;
	overflow:hidden;
	background-image: url(tube.png); 
	background-repeat: no-repeat;
	
	border-top: var(--Top) dashed var(--ColorFon);
	background-position-y: calc(var(--Top) * (-1));
	border-left: var(--Left) dashed var(--ColorFon);
	background-position-x: calc(var(--Left) * (-1));
	border-bottom: var(--Bottom) dashed var(--ColorFon);
	border-right: var(--Right) dashed var(--ColorFon);

	height: calc(var(--Step) - var(--Top) - var(--Bottom));
	width: calc(var(--Step) - var(--Left) - var(--Right));
}

.tube div[name*="top"] {
	--Top: 0px;
}

.tube div[name*="bottom"] {
	--Bottom: 0px;
}

.tube div[name*="left"] {
	--Left: 0px;
}

.tube div[name*="right"] {
	--Right: 0px;
}


/* ---------------------------------------------- */

.pump > div {
	float:left;
	overflow:hidden;
	width:var(--Step); 
	height:var(--Step);
	background-image: url(pump.png); 
	background-repeat: no-repeat;
	background-position: center center;
}

.pump > div[data-st=ON] {
	background-image: url(pump_on.png); 
}

.pump > div[data-st=OFF] {
	background-image: url(pump_off.png); 
}

.pump > div[data-st^=E] {
	background-image: url(pump_off.png); 
}

.pump p{
	text-align: center;
    margin-top: 0px;
}

.pump p[name=status]:after {
	content: attr(data-st);
}


/* ---------------------------------------------- */

.time1 > div {
	float:left;
	overflow:hidden;
	width:var(--Step); 
	height:var(--Step);
}

.time1 p{
	margin-left: 5px;
}

.time1 p[name=value]{
	margin-left: 5px;
	margin-top: 35px;
}

.time1 p[name=value]:after{
	content: attr(data-v);
}


/* ---------------------------------------------- */

.set {
	cursor: pointer;
}

.set:hover {
}



 

vde69
Offline
Зарегистрирован: 10.01.2016

Пока клиенты отваливаются примерно через 10 мин. Наверно это внутренний таймаут. Но сервер при этом работает, если страницу обновить, то все сново работает.

vde69
Offline
Зарегистрирован: 10.01.2016

И кстати пока никаких перезагрузок

vde69
Offline
Зарегистрирован: 10.01.2016

добавил кусочек для отслеживания количества активных сессий  (пока играюсь с пределом в 4шт)

void loop() {
	// обработчик UART
	LoopReadUart();

#ifdef ON_DEBUG_ECHO
char old_debug_client[MAX_SRV_CLIENTS];
memcpy(&(old_debug_client[0]), &(debug_client[0]), MAX_SRV_CLIENTS+1);
#endif

	uint8_t i;
	// сначала закроем все просроченные сессии
	for(i = 0; i < MAX_SRV_CLIENTS; i++){
		if ( clients[i].client && !clients[i].client.available()) {
			if (time_pause(clients[i].p.time_loop_new, millis()) > 10000) {
				// держим не более 10 сек
				clients[i].client.stop();
				clear_param(&(clients[i].p));
			}
		}
	}

	// попытка создание новых клиентских сессии
	if (server.hasClient()){
		for(i = 0; i < MAX_SRV_CLIENTS; i++){
			if (!clients[i].client || !clients[i].client.connected()){
				clients[i].client = server.available();
				continue;
			}
		}
		//нет свободных соеденинений
		WiFiClient serverClient = server.available();
		if (serverClient) {
			while (serverClient.available()) { serverClient.read(); }
			out_503(&serverClient);
			serverClient.stop();
		}
	}

	// для каждого активного клиента запускаем обработчик цикла
	for(i = 0; i < MAX_SRV_CLIENTS; i++){
		if ( clients[i].client ) {
			LoopReadWiFi(&(clients[i]));
		}
	}

#ifdef ON_DEBUG_ECHO
for(i = 0; i < MAX_SRV_CLIENTS; i++){
	if ( clients[i].client ) { debug_client[i] = '+'; }
	else { debug_client[i] = '-'; }
}
if (strcmp(&debug_client[0],&old_debug_client[0]) != 0) {
Serial.print("Sesion: ");
Serial.print(debug_client);
Serial.print("; Free RAM="); 
Serial.print(ESP.getFreeHeap());
Serial.println();
}
#endif

}

 

 

вот результат, там где + это активная сессия, и кстати даже для одного реального сеанса открывается иногда и по 2 сессии, судя по всему это параллельная скачка файлов, и реально шустрее работает

..

WiFi connected
Server started
192.168.10.101
Sesion: +---; Free RAM=45456
Sesion: ----; Free RAM=45320
Sesion: +---; Free RAM=45464
Sesion: ----; Free RAM=45328
Sesion: ++--; Free RAM=45160
Sesion: ----; Free RAM=44888
Sesion: +---; Free RAM=44688
Sesion: ----; Free RAM=44552
Sesion: +---; Free RAM=44832
Sesion: ----; Free RAM=44696
Sesion: +---; Free RAM=44640
Sesion: ----; Free RAM=44504
Sesion: +---; Free RAM=44640
Sesion: ----; Free RAM=44504
Sesion: +---; Free RAM=44080
Sesion: ++--; Free RAM=43992
Sesion: +---; Free RAM=43856
Sesion: ++--; Free RAM=44000
Sesion: +---; Free RAM=43864
Sesion: ++--; Free RAM=44328
Sesion: +---; Free RAM=44192
Sesion: ++--; Free RAM=43992
Sesion: +---; Free RAM=43856
Sesion: ++--; Free RAM=44328
Sesion: +---; Free RAM=44192
Sesion: +++-; Free RAM=43360
Sesion: ++--; Free RAM=43200
Sesion: +++-; Free RAM=42192
Sesion: +-+-; Free RAM=43512
Sesion: +---; Free RAM=44264
Sesion: ++--; Free RAM=43904
Sesion: +++-; Free RAM=43992
Sesion: ++++; Free RAM=42136
Sesion: +-++; Free RAM=42656
Sesion: +--+; Free RAM=42680
Sesion: +---; Free RAM=44104
Sesion: ++--; Free RAM=44136
Sesion: +---; Free RAM=44216
Sesion: ++--; Free RAM=44136
Sesion: +---; Free RAM=44328
Sesion: ++--; Free RAM=44136
Sesion: +---; Free RAM=44216
Sesion: ++--; Free RAM=43800
Sesion: +++-; Free RAM=43168
Sesion: ++--; Free RAM=43032
Sesion: +---; Free RAM=44080
Sesion: ++--; Free RAM=44136
Sesion: +---; Free RAM=44216
Sesion: ++--; Free RAM=44136
Sesion: +---; Free RAM=44216
Sesion: ++--; Free RAM=43576
Sesion: +---; Free RAM=44216
Sesion: ++--; Free RAM=44136
Sesion: +---; Free RAM=44216
Sesion: ++--; Free RAM=44136
Sesion: +---; Free RAM=44328
Sesion: ++--; Free RAM=43576
Sesion: +---; Free RAM=44216
Sesion: ++--; Free RAM=43800
Sesion: +++-; Free RAM=43888
Sesion: ++--; Free RAM=43752
Sesion: +---; Free RAM=44160
Sesion: ++--; Free RAM=44136
Sesion: +---; Free RAM=44216
Sesion: ++--; Free RAM=43800
Sesion: +++-; Free RAM=43888
Sesion: ++--; Free RAM=43752
Sesion: +---; Free RAM=44080
Sesion: ++--; Free RAM=44136
Sesion: +---; Free RAM=44216
Sesion: ++--; Free RAM=44136
Sesion: +++-; Free RAM=43168
Sesion: ++--; Free RAM=43032
Sesion: +---; Free RAM=44080
Sesion: ++--; Free RAM=43576
Sesion: +---; Free RAM=44328
Sesion: ++--; Free RAM=44136
Sesion: +++-; Free RAM=43888
Sesion: ++--; Free RAM=43752
Sesion: +---; Free RAM=43968
Sesion: ++--; Free RAM=43576
Sesion: +---; Free RAM=44216
Sesion: +++-; Free RAM=43888
Sesion: ++--; Free RAM=43752
Sesion: +---; Free RAM=44160
Sesion: ++--; Free RAM=44136
Sesion: +---; Free RAM=44216
Sesion: ++--; Free RAM=43800
Sesion: +++-; Free RAM=43888
Sesion: ++--; Free RAM=43752
Sesion: +---; Free RAM=44160
Sesion: ++--; Free RAM=43576
Sesion: +---; Free RAM=44216
Sesion: ++--; Free RAM=44136
Sesion: +++-; Free RAM=43888
Sesion: ++--; Free RAM=43752
Sesion: +---; Free RAM=44080
Sesion: ++--; Free RAM=44136
Sesion: +---; Free RAM=44216
Sesion: ++--; Free RAM=43800
Sesion: +++-; Free RAM=43888
Sesion: ++--; Free RAM=43752
Sesion: +---; Free RAM=43968
Sesion: ++--; Free RAM=44136
Sesion: +---; Free RAM=44216
Sesion: ++--; Free RAM=43800
Sesion: +++-; Free RAM=43272
Sesion: ++--; Free RAM=43136
Sesion: +---; Free RAM=43968
Sesion: ++--; Free RAM=44136
Sesion: +---; Free RAM=44216
Sesion: ++--; Free RAM=43800
Sesion: +++-; Free RAM=43168
Sesion: ++--; Free RAM=43032
Sesion: +---; Free RAM=43968
Sesion: ++--; Free RAM=44136
Sesion: +---; Free RAM=44216
Sesion: ++--; Free RAM=43800
Sesion: +++-; Free RAM=43168
Sesion: ++--; Free RAM=43032
Sesion: +---; Free RAM=43968
Sesion: ++--; Free RAM=44136
Sesion: +---; Free RAM=44216
Sesion: ++--; Free RAM=43456
Sesion: +++-; Free RAM=41984
Sesion: ++--; Free RAM=44080
Sesion: +++-; Free RAM=43552
Sesion: ++++; Free RAM=42920
Sesion: +++-; Free RAM=43720
Sesion: ++--; Free RAM=43912
Sesion: ++++; Free RAM=43640
Sesion: +++-; Free RAM=43720
Sesion: ++--; Free RAM=43912
Sesion: +---; Free RAM=43888
Sesion: ++--; Free RAM=43608
Sesion: +---; Free RAM=43472
Sesion: ++--; Free RAM=43832
Sesion: +---; Free RAM=43808
Sesion: ++--; Free RAM=43608
Sesion: +---; Free RAM=43472
Sesion: ++--; Free RAM=43832
Sesion: +---; Free RAM=43696
Sesion: ++--; Free RAM=43944
Sesion: +---; Free RAM=43808
Sesion: ++--; Free RAM=43568
Sesion: +---; Free RAM=43432
Sesion: ++--; Free RAM=43568
Sesion: +---; Free RAM=43432
Sesion: ++--; Free RAM=43800
Sesion: +---; Free RAM=43664
Sesion: ++--; Free RAM=44024
Sesion: +---; Free RAM=44000
Sesion: ++--; Free RAM=43800
Sesion: +---; Free RAM=44024
Sesion: ++--; Free RAM=41712
Sesion: +---; Free RAM=42984
Sesion: +++-; Free RAM=43888
Sesion: ++--; Free RAM=43752
Sesion: +---; Free RAM=44160
Sesion: ++--; Free RAM=44136
Sesion: +---; Free RAM=44216
Sesion: ++--; Free RAM=44136
Sesion: +---; Free RAM=44216
Sesion: ++--; Free RAM=43576
Sesion: +---; Free RAM=44328
Sesion: ++--; Free RAM=43576
Sesion: +---; Free RAM=44216
Sesion: ++--; Free RAM=44136
Sesion: +---; Free RAM=44216
Sesion: ++--; Free RAM=44136
Sesion: +---; Free RAM=44216
Sesion: ++--; Free RAM=44136
Sesion: +---; Free RAM=44216

 

vde69
Offline
Зарегистрирован: 10.01.2016

в библиотеке есть константа 

MAX_PENDING_CLIENTS_PER_PORT=5

ее можно переопределить на большее число, но надо смотреть за памятью.

вроде как на значение в 5 сесий памяти должно хватать

Logik
Offline
Зарегистрирован: 05.08.2014

vde69 пишет:

в библиотеке есть константа 

MAX_PENDING_CLIENTS_PER_PORT=5

ее можно переопределить на большее число, но надо смотреть за памятью.

Так собственно в том и вопрос. Как только начнет расти LoopReadWiFi, то все  что в ней выделится надо умножать на 5. LwIP какой версии? Если 2.0 то она проблемная. Например http://arduino.ru/forum/apparatnye-voprosy/polzuet-li-kto-wifi-moduli-esp8266-podelites-vpechatleniyami?page=23#comment-559687 А 1.4 памяти больше требует.

vde69
Offline
Зарегистрирован: 10.01.2016

Надо понимать, что количество сессий и количество клиентов - это разное. Один клиент может жрать и 5 сессий... 

я это реально наблюдал, тут самое главное - это ассинхронно обрабатывать все открытые сессии, это можно делать или через прерывания или в главном цикле, я пошел вторым путем, он не самый лучший, но более надежный и более простой в понимании (не надо никаких мьютексов и семафоров).

Я разумеется понимаю, что выставить в инет еспшку это просто глупость, а вот например реализовать к ней несколько параллельных веб клиентов это уже интересно.

Лично мне больше 5 клиентов не понадобится, а сесси реально долго не живут и освободожаются быстро.

Хотя есть тут какая-то фигня когда он перестает нормально отвечать на JSON, при этом сессия создается и сразу рубится, но где именно рубится я пока не понял.

 

Короче судя по всему лично мне функционала на 5 клиентов вполне хватает. Я пока буду копать в сторону стабильности и авторизацию доделаю. 

Потом наверно весь труд задокументирую и выложу в "проекты" или еще куда

 

Думаю пока сделать несколько параметров (в процентах) которые будут отображать

1. загрузку параллельных соединений (1 соединение = 20%)

2. загрузку памяти (60к свободной = 0%, 10к свободной = 100%)

3. и так далее, что еще мне понадобится не знаю

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Чем с протокольной/программной точки зрения измерения в клиентах лучше измерения в сессиях? Какой смысл вообще измерять в клиентах?

vde69
Offline
Зарегистрирован: 10.01.2016

sadman41 пишет:
Чем с протокольной/программной точки зрения измерения в клиентах лучше измерения в сессиях? Какой смысл вообще измерять в клиентах?

для меня разницы особой нет, по тому как и клиент и сессия вроде как идентифицируются одинаково IP+Port, 

но если копать глубоко - там разница уже будет

sadman41
Offline
Зарегистрирован: 19.10.2016

Разница в человеческой голове (на прикладном уровне). Вебсерверу должно быть фиолетового.

Но вот считать в клиентах - так же, как и в попугаях. Цифра есть, но смысла нет.

Logik
Offline
Зарегистрирован: 05.08.2014

//это можно делать или через прерывания....

У ESP8266 нельзя. С прерываниями там вообще безнадега. Там я ссылку бросал, читай, там дальше и про прерывания.

 

//60к свободной 

это откуда столько то.. 45КБ мелькало там максимум.. 

//никаких мьютексов и семафоров

отбрось эти пережитки больших машин следом за многопоточностью. Вот то цикл LoopReadWiFi - не просто лучшее. Это единственное по сути. 

vde69
Offline
Зарегистрирован: 10.01.2016

sadman41 пишет:
Разница в человеческой голове (на прикладном уровне). Вебсерверу должно быть фиолетового. Но вот считать в клиентах - так же, как и в попугаях. Цифра есть, но смысла нет.

Не совсем так, клиентский сокет может не порождать клиентской сессии. Тем не менее соединение будет висеть и жрать ресурсы. По этому ограничение которое прописано в библиотеке - это по существу ограничение на ответ сервера а ограничение по сесиям это другое, тут например может возникать ошибка http  503.

Если рассматривать уровень прикладного сервера, то ограничение по клиентам - предназначено в перую очередь для борьбы с ддос атаками, и оно не имеет обрабаботку внутри прикладной части сервера (оно в ядре), 

а вот ограничения на сесии - это уже прикладной уровень...