Отправка и приём данных

Для отправки и приёма зашифрованных данных предусмотрен отдельный набор "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, которое показывает длину расшифрованных данных, доступных для извлечения.

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