Итак, BitTorrent-рукопожатие состоит из:
- байт со значением 19 (длина следующей строки);
- строка UTF-8 "Протокол BitTorrent" (такая же, как в ASCII);
- восемь зарезервированных байтов, используемых для маркировки расширений;
- 20 байтов хэша торрент-информации;
- 20 байтов идентификатора пира.
Итак, вы можете начать с получения достаточно большого буфера для сообщения о рукопожатии:
const int handshake_size = 1+19+8+20+20;
char handshake[handshake_size];
Предварительный расчет смещений также помогает:
const int protocol_name_offset = 1;
const int reserved_offset = protocol_name_offset + 19;
const int info_hash_offset = reserved_offset + 8;
const int peer_id_offset = info_hash_offset + 20;
И тогда вам просто нужно заполнить его.
const char prefix = 19;
const std::string BitTorrent_protocol = "BitTorrent protocol";
handshake[0] = prefix; // length prefix of the string
std::copy(BitTorrent_protocol.begin(), BitTorrent_protocol.end(),
&handshake[protocol_name_offset]); // protocol name
И так далее для остальных данных.
Затем буфер можно отправить напрямую в любой сетевой API, который вы будете использовать.
Чтобы прочитать ответ, вы извлекаете части буфера и соответственно проверяете:
if(reply[0] != prefix) {
// fail
}
if(!std::equal(BitTorrent_protocol.begin(), BitTorrent_protocol.end(), &reply[protocol_name_offset]) {
// fail
}
и т. Д.
Чтение и запись структур непосредственно из сети не рекомендуется, поскольку требуется полный контроль над макетом, иначе сообщение будет искажено.