На странице спецификации протокола BitTorrent
, сказано, что сообщение рукопожатия, должно быть отправлено первым, после подключения. И указано следущяя структура этого сообщения:
Handshake
The handshake is a required message and must be the first message transmitted by the client. It is (49+len(pstr)) bytes long.
handshake: <pstrlen><pstr><reserved><info_hash><peer_id>
pstrlen: string length of , as a single raw byte
pstr: string identifier of the protocol
Так вот, я подумал что сообщение должно формироваться следущим образом:
const string protocol = "BitTorrent protocol";
string request = $"<{protocol.Length}>" + // <pstrlen>
$"<{protocol}>" + // <pstr>
"< >" + // <reserved>
$"<{torrentFile.GetInfoHash()}>" + // <info_hash>
"<-AZ206088->"; // <peer_id>
Однако это не работает, т.к. при отправке сообщения одному из пиров, он не отвечает, т.е. не шлет в ответ ничего, думаю я не правильно сформировал сообщение рукопожатия.
Как правильно сформировать сообщение?
Все строковые константы начисто скопированы из вопроса.
Судя по протоколу можно сделать так:
1) Получаем байты из строки протокола. В доках написано, что всё в ASCII
const string protocol = "BitTorrent protocol";
var content = Encoding.ASCII.GetBytes(protocol);
2) Создаём массив нужного размера
var message = new byte[49 + content.Length];
3) Записываем байтовую длину строки протокола
int currentPosition = 0;
message[currentPosition++] = (byte) content.Length;
3) Записываем само байтовое представление
Array.Copy(content, 0, message, currentPosition, content.Length);
currentPosition += content.Length;
4) Оставляем 8 пустых байт по воле доков с:
currentPosition += 8;
5) Копируем 20-байтовый хэш
Array.Copy(torrentfile.GetInfoHashBytes(), 0, message, currentPosition, 20);
urrentPosition += 20;
6) Получаем байтовое представление peer строки и записываем его
Если вы следуете Azureus-style, то у вас указан неверный peer, т.к. этот стиль подразумевает:
'-', two characters for client id, four ascii digits for version number, '-', followed by random numbers.
const string peer = "-AZ206088-";
var peerTextContent = Encoding.ASCII.GetBytes(peer);
Array.Copy(peerTextContent, 0, message, currentPosition, peerTextContent.Length);
currentPosition += peerTextContent.Length;
7) В протоколе сказано, что peer должен состоять ровно из 20 байт, и если не хватает, то заполнить случайными числами, а т.к. у нас нет лишних байт в массиве, то мы заполняем его до конца, т.к. это будет соответствовать тому, сколько байт не хватило в peer
new Random().NextBytes(message.AsSpan(currentPosition));
8) Отправляем наш массив message
куда нужно :3
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Как выполнить открытие формы, после нажатия определенной последовательности клавиш (стрелок) на клавиатуре? Прошу предоставить пример кода,...
Есть отдельный UserControl, который я передаю в TabPage и юзаю его в TabControl
Работаю с WPF с применением паттерна MVVMСтолкнулся с проблемой, создал UserControl(далее UC) один общий который будет несколько раз использоваться:
Чтоб к каждому члену этого списка соотвецвовало 2 переменные byte и 2 string