我正在写我的Torrent客户端,当我需要发送一个带有信息哈希的GET请求时,我被卡住了。当发送请求时,我需要正确地格式化它。结果,URLEncode与它的名称不匹配,我知道的其他方法不能引导我到达目标。(抱歉英语不好)
我尽量不使用第三方库。
正如我所看到的,我需要"从十六进制表示转换为散列的字节串值",但是我尝试这样做并没有得到想要的结果。
我找到了这些答案和其他一些答案,但它们都是在其他编程语言上,我无法理解,也无法在我的代码中重现它们。link vb.netlink rust
我还找到了Bittorent library,但即使使用它的编码方法,我的程序也没有发生任何变化。
UPD 1:我在bencoding时得到的信息散列:0a85522a2f09e42f3d63a89a0d45e4589f8b904c中所列的数字
以下是我在Wireshark中看到的情况:
https://bt.toloka.to/announce/h=IT5FwgeUF1& (Tracker blocks most countries so if you want to check, use VPN (recomend Netherlands))
&info_hash=%0A%85R%2A%2F%09%E4%2F%3Dc%A8%9A%0DE%E4X%9F%8B%90L
&peer_id=-UT360W-%FE%B5%95%1A%88%0A%DF%97K%E9%FD%23
&port=19708
&uploaded=0
&downloaded=0
&left=16421367202
&corrupt=0
&key=A36E3AE9
&event=stopped
&numwant=0
&compact=1
&no_peer_id=1
它对信息散列进行编码,如下所示:第一节第二节第三节第四节第四节
UPD 2:
我的问题是,我不能实现URL编码。我需要在这里转换这个:
0a85522a2f09e42f3d63a89a0d45e4589f8b904c中所列的数字
变成这样:
第一页第二页第三页第四页
我试图从stackoverflow上的其他答案重写代码,但没有任何明智的成功。
String a = "0a85522a2f09e42f3d63a89a0d45e4589f8b904c";
byte[] hash = a.getBytes(StandardCharsets.UTF_8);
StringBuilder res = new StringBuilder();
for(char element : a.toCharArray()){
if(Character.getNumericValue(element) <= 127){
char[] result = URLEncoder.encode(String.valueOf(element), String.valueOf(StandardCharsets.UTF_8)).toCharArray();
if(result[0] == '%'){
res.append(toLowerCase(result));
}else{
char[] reinfo = new char[result.length + 1];
reinfo[0] = '%';
for(int i = 0; i < result.length; i++){
reinfo[i + 1] = result[i];
}
res.append(toLowerCase(reinfo));
}
}
}
2条答案
按热度按时间iqjalb3h1#
信息哈希是20字节的二进制数据,十六进制字符串(40个字符)已经是一种编码形式。因此,最简单的方法是对所有字节进行百分比编码,无论它们是否可以表示为ASCII。
例如,
0x8552
可以被编码为%85R
或%85%52
,后者空间效率较低,但前者作为起点更容易实现。e1xvtsh32#
我确实设法用java做了,正如我所注意到的,hash_info中只使用了a-z,A-Z,0-9个字符,所以你所要做的就是把十六进制转换成相应的字母。(有必要的信息here)
下面是我得到的代码:
输入数据:
0a 85522 a2 f09 e42 f3 d 63 a89 a0 d45 e4589 f8 b 904 c中所列的数字
结果:
第一页第二页第三页第四页
谢谢你给那些想帮忙的人的建议和忠告。