Приём данных в режиме TCP

Мы уже объясняли, что буферы RX и TX работают по-разному в режимах TCP и UDP. В этом разделе рассказано, как принимать данные, когда сокет использует протокол TCP.

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

sub on_sys_init
	while sock.rxlen = 0
	wend ' basically keeps executing again and again as long as sock.rxlen = 0
	s = sock.getdata(255) ' once loop is exited, it means data has arrived. We extract it.
end sub

Так работать можно, но программа навсегда застрянет в одном обработчике события (например, on_sys_init), а другие события не получат шанса выполниться. Это пример блокирующего кода, из-за которого система может зависнуть. Конечно, можно использовать оператор doevents, но в целом блокирующего подхода советуем избегать.

Поскольку наша платформа событийно-ориентированная, о появлении новых данных должны сообщать события. Есть событие on_sock_data_arrival, которое генерируется всякий раз, когда в буфере RX есть данные:

sub on_sock_data_arrival
	dim s as string
	s = sock.getdata(255) ' Extract the data -- but in a non-blocking way.
	' .... code to process data ....
end sub

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

Это значит, что при обработке этого события вовсе не обязательно забирать все данные из буфера RX. Можно обработать часть данных, и после выхода из обработчика будет сгенерировано новое событие того же типа.

Вот правильный пример обработки поступающих данных сокета через событие on_sock_data_arrival. Этот пример реализует возврат данных (loopback): всё, что принял сокет, тут же отправляется обратно.

sub on_sock_data_arrival
	sock.setdata(sock.getdata(sock.txfree))
	s = sock.send
end sub

Этот loopback нужно сделать как можно эффективнее, но при этом нельзя переполнить буфер TX. Поэтому нельзя просто копировать все поступающие данные из буфера RX в буфер TX: надо проверить, сколько свободного места в буфере TX. Именно это делает первая строка кода: sock.getdata берёт из буфера RX столько данных, сколько возможно, но не больше sock.txfree (свободного места в буфере TX). Вторая строка просто отправляет данные.

Примечание

На самом деле за один проход этот вызов обработает не более 255 байт. Хотя данные как будто копируются напрямую из буфера RX в буфер TX, на деле это происходит через временную строковую переменную, которая создаётся автоматически. В этой платформе строковые переменные не могут превышать 255 байт.

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