Отправка и приём данных
Для отправки и приёма зашифрованных данных предусмотрен отдельный набор "TLS"-свойств и методов. Они похожи на свои незашифрованные аналоги, предназначенные для работы с обычными данными, но не совпадают с ними полностью. Все отличия собраны в таблице ниже:
| Обычные данные | Данные TLS | Комментарий |
| Метод sock.getdata | Метод sock.tlsgetdata | |
| Свойство только чтение sock.newtxlen | --- | Для буферов TLS не реализовано. |
| Метод sock.notifysent | --- | Для асинхронной отправки данных по-прежнему можно использовать sock.notifysent и on_sock_data_sent. |
| Метод sock.peekdata | Метод sock.tlspeekdata | |
| Метод sock.rxclear | --- | Для буферов TLS не реализовано. Не вызывайте на сокете с включённым TLS. |
| Свойство только чтение sock.rxlen | Свойство только чтение sock.tlsrxlen | |
| Метод sock.setdata | Метод sock.tlssetdata | В отличие от sock.setdata, sock.tlssetdata возвращает число байт, фактически принятых в буфер TLS TX. Это "оправдывает" отсутствие свойств "sock.tlstxfree" и "sock.tlstxlen". |
| Метод sock.send | --- | Для отправки данных по-прежнему нужно использовать sock.send |
| Метод sock.txclear | Для буферов TLS не реализовано. Не вызывайте на сокете с включённым TLS. | |
| Свойство только чтение sock.txfree | --- | При помещении данных в буфер TLS TX проверяйте число принятых байт; его возвращает sock.tlssetdata. |
| Свойство только чтение sock.txlen | --- | При помещении данных в буфер TLS TX проверяйте число принятых байт; его возвращает sock.tlssetdata. |
Отправка зашифрованных данных
Чтобы подготовить данные к передаче через TLS-сокет, вызовите sock.tlssetdata, который принимает строковый параметр с данными. Данные помещаются в буфер TLS TX. Обратите внимание: данные ещё не отправлены. Это задача sock.send, который зашифрует данные, поместит их в буфер передачи и запустит отправку.
'This example code sends an HTTP GET request; note the carriage returns,
'which are used to signal to the server the end of each parameter
sock.tlssetdata("GET / HTTP/1.1\r\nHost:your.example.com\r\n\r\n")
sock.send()
Если данных, которые вы хотите поместить в буфер TLS TX, больше, чем в нём свободного места, sock.tlssetdata поместит в буфер как можно больше данных, а остальное отбросит. Поскольку sock.tlssetdata возвращает число байт, которое удалось сохранить в буфере TLS, можно добавить логику отслеживания хода передачи и последовательно вызывать sock.tlssetdata и sock.send, пока все данные не будут отправлены.
Пример "блокирующего" кода, который отправляет файл через TLS-сокет:
romfile.open("test.txt") 'Replace "test.txt" with the file containing your data
dim datasent as dword = 0 'This variable tracks the total amount of data sent
dim sent as dword = 0 'This variable tracks the amount of data successfully
'placed in the TLS buffer
dim s as string = "" 'This variable holds the data being sent
while datasent <> romfile.size 'This loops operations until the entire file is read
if s = "" then 'If s is empty (i.e., at the start of transmission),
s = romfile.getdata(255) 'this reads the next 255 bytes and places them in s
end if
sent = sock.tlssetdata(s) 'The data is placed in the TLS buffer by
'sock.tlssetdata and the return is passed to the sent
'variable to keep track of the transmission's progress
if sent <> 255 then
s = right(s,len(s)-sent) 'This retains the data that did not fit in the TLS buffer
'so it can be added next time around the loop
sock.send()
else
s = "" 'This clears the variable s so more data can be read
end if
datasent = datasent + sent 'This keeps track of how much data has been sent
wend
sock.send() 'This sends anything left in the TLS buffer
В следующем примере показан "неблокирующий" асинхронный способ отправки большого блока данных: sock.notifysent и on_sock_data_sent используются так же, как в незашифрованном обмене. Сначала, в начале файла проекта main.tbs:
dim datasent as dword = 0 'These variables are now global
dim sent as dword = 0
dim s as string = ""
declare sub send_file() 'This declares a function that will contain the
'core code to transmit data, which allows for
'it to be called sequentially as needed
Следующий фрагмент нужно разместить там, где в вашем коде начинается передача. Например, это может быть обработчик события on_button_pressed:
sub on_button_pressed()
romfile.open("test.txt") 'Replace "test.txt" with the file containing your data
datasent = 0 'Reset the value of the variables before starting a
sent = 0 'new transmission
s = ""
send_file()
end sub
Вот код объявленной ранее процедуры send_file:
sub send_file()
if datasent <> romfile.size then 'This checks whether the transmission has been completed
if s = "" then
s = romfile.getdata(255)
end if
sent = sock.tlssetdata(s)
if sent <> 255 then
s = right(s,len(s)-sent)
else
s = ""
end if
datasent = datasent + sent
end if
sock.notifysent(0) 'This causes the on_sock_data_sent event to be
'generated, which will be used to continue the
'transmission until the transfer is completed
sock.send() 'This sends anything left in the TLS buffer
end sub
Наконец, мы используем обработчик события on_sock_data_sent, чтобы при необходимости вызывать send_file.
sub on_sock_data_sent()
if datasent <> romfile.size then 'This checks whether the transmission has been completed
send_file() 'and calls send_file() if not
else
sys.debugprint("Mission Complete"+"\r\n") 'This announces when the transmission has
'has been completed
end if
end sub
Приём зашифрованных данных
При приёме зашифрованных данных sock.tlsgetdata забирает данные из буфера приёма, расшифровывает их, помещает расшифрованные данные в буфер TLS RX, а затем извлекает из буфера TLS RX запрошенное число байт (или сколько есть, если их меньше).
В следующем примере обработчик события on_sock_data_arrival используется для обработки зашифрованных данных по мере их поступления. В режиме TLS это событие возникает, когда в буфере TLS RX (а не в буфере приёма) есть хотя бы один байт данных:
sub on_sock_data_arrival()
sys.debugprint(sock.tlsgetdata(255) 'This will print the decrypted data received via TLS
'into the Output panel in TIDE
end sub
Метод sock.tlspeekdata позволяет "подсмотреть" расшифрованные данные в буфере TLS RX, не удаляя их из буфера. Есть и свойство только чтение sock.tlsrxlen, которое показывает длину расшифрованных данных, доступных для извлечения.