Генерация динамических HTML-страниц

"Печать" динамических HTML-данных

Чаще всего код Tibbo BASIC/C, включённый в HTML-страницу, нужен для формирования динамического HTML-содержимого (то есть для отправки браузеру динамически сгенерированных данных). Это делается так же, как отправка данных в обычном режиме данных: сначала методом sock.setdata задаются данные для отправки, затем методом sock.send они передаются на отправку.

Пример HTML-страницы, которая проверяет состояние одного из входов объекта io и выводит это состояние на странице:

<!DOCTYPE HTML public "-//W3C//DTD W3 HTML//EN">
<HTML>
<BODY>
	The state of line 0 is:!<br>
	<?
		'This is a BASIC code fragment. Get the state of the line.
		io.num=0
		if io.state= LOW then
			sock.setdata("LOW")
		else
			sock.setdata("HIGH")
		end if
		sock.send
	?>
</BODY>
</HTML>
Совет

Обратите внимание: sock.num задавать не пришлось - он устанавливается автоматически, когда управление передаётся Tibbo BASIC/C!

Следите, чтобы данные не обрезались!

Приведённый пример выглядит верным, и в данном случае он будет работать нормально: перед местом генерации динамического содержимого статических данных немного, да и самого динамического содержимого тоже немного. Вообще же рассчитывать на то, что в буфере передачи хватит места, когда понадобится положить в него данные, нельзя! Если не быть внимательным, генерируемые динамические данные могут обрезаться!

Чтобы этого избежать, всегда проверяйте, достаточно ли свободного места, прежде чем помещать данные в буфер передачи. Это справедливо и для обычного режима данных, а не только для HTTP-обработки; мы уже затрагивали эту тему в разделе Отправка данных TCP и UDP. Для HTTP отличие в том, что событие on_sock_data_sent нельзя использовать, чтобы вас "уведомили", когда буфер передачи освободится!

Единственное решение для HTTP - ждать в цикле, пока не появится нужный объём места. Естественно, блокировать всё устройство не нужно, поэтому "вежливое" ожидание должно включать оператор doevents:

<?
	dim s as string(4)
?>
<!DOCTYPE HTML public "-//W3C//DTD W3 HTML//EN">
<HTML>
<BODY>
	The state of line 0 is:!<br>
	<?
		'This is a BASIC code snippet. Get the state of the line.
		io.num=0
		if io.state= LOW then
			s="LOW"
		else
			s=HIGH
		end if
		'and now we wait till the TX buffer has enough free space
		while sock.txfree<len(s)
			doevents
		wend
		'OK, so necessary space is now available!
		sock.setdata(s)
		sock.send
	?>
</BODY>
</HTML>

Теперь динамическое содержимое формируется надёжно, и работа не блокируется! По мере накопления опыта с HTML вы увидите, что оператор doevents приходится использовать довольно часто.

Особый случай: doevents и одновременный запрос одного и того же файла

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

Вполне возможно и так, что при выполнении процедуры Tibbo BASIC/C из первого "экземпляра" файла выполнение доходит до doevents, и начинается обработка второго экземпляра того же файла. Ведь doevents позволяет выполняться другим событиям, в том числе активности в других сокетах.

Если бы той же процедуре Tibbo BASIC/C разрешили выполниться повторно, возникла бы рекурсия: попытка выполнить фрагмент кода, который уже выполняется! Рекурсия не допускается, поэтому виртуальная машина не станет входить в код повторно сразу. Вместо этого второй экземпляр HTML-страницы будет "ждать", пока первый не закончит выполнять эту процедуру. После этого та же процедура выполнится для второго экземпляра. Такое поведение появилось в TiOS V1.2. В более ранних версиях выполнение процедуры для второго экземпляра HTML-страницы просто пропускалось, что неправильно!

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

Недопустимые символы

HTTP запрещает использовать некоторые символы: произвольный код из таблицы ASCII отправлять нельзя. Когда вы используете sock.setdata и sock.send, вы "печатаете" данные прямо в браузер. Избегать недопустимых символов и вместо них использовать "%xx" должна ваша программа.

Исходный материал Tibbo обновлён 12 сентября 2022Оригинал на docs.tibbo.com · Сообщить об ошибке