{"id":344800,"date":"2023-01-31T21:00:34","date_gmt":"2023-01-31T21:00:34","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=344800"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=344800","title":{"rendered":"<span>Bittorrent \u0441 \u043d\u0443\u043b\u044f \u043d\u0430 Go<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/43d\/908\/e6f\/43d908e6f14b60294b8bb69b5e8ad600.png\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/43d\/908\/e6f\/43d908e6f14b60294b8bb69b5e8ad600.png\"\/><\/p>\n<p>  <\/p>\n<p>BitTorrent \u2014 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u043e\u0432 \u0447\u0435\u0440\u0435\u0437 \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442. \u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0439 \u043a\u043b\u0438\u0435\u043d\u0442\/\u0441\u0435\u0440\u0432\u0435\u0440, \u043a\u043e\u0433\u0434\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043a\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u044e\u0442\u0441\u044f \u043a \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u0443 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0444\u0438\u043b\u044c\u043c\u0430 \u043d\u0430 Netflix \u0438\u043b\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0432\u0435\u0431-\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b), \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u0438 \u0441\u0435\u0442\u0438 BitTorrent, \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0435 <strong>\u043e\u0434\u043d\u043e\u0440\u0430\u043d\u0433\u043e\u0432\u044b\u043c\u0438 \u0443\u0437\u043b\u0430\u043c\u0438<\/strong>, \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u044e\u0442 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u044b \u0444\u0430\u0439\u043b\u043e\u0432 \u0434\u0440\u0443\u0433 \u0441 \u0434\u0440\u0443\u0433\u0430. \u042d\u0442\u043e \u0442\u043e, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 BitTorrent <strong>\u043e\u0434\u043d\u043e\u0440\u0430\u043d\u0433\u043e\u0432\u044b\u043c<\/strong> \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u043e\u043c. \u0418\u0441\u0441\u043b\u0435\u0434\u0443\u0435\u043c, \u043a\u0430\u043a \u043e\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u0438 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c \u043e\u0434\u043d\u043e\u0440\u0430\u043d\u0433\u043e\u0432\u044b\u0435 \u0443\u0437\u043b\u044b \u0438 \u043e\u0431\u043c\u0435\u043d\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0441 \u043d\u0438\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438.<\/p>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/43d\/908\/e6f\/43d908e6f14b60294b8bb69b5e8ad600.png\" alt=\"\u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430, \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0449\u0430\u044f \u0440\u0430\u0437\u043d\u0438\u0446\u0443 \u043c\u0435\u0436\u0434\u0443 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f\u043c\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\/\u0441\u0435\u0440\u0432\u0435\u0440 (\u0432\u0441\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u044b \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u044e\u0442\u0441\u044f \u043a \u043e\u0434\u043d\u043e\u043c\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u0443) \u0438 \u043e\u0434\u043d\u043e\u0440\u0430\u043d\u0433\u043e\u0432\u044b\u043c\u0438 (\u043e\u0434\u043d\u043e\u0440\u0430\u043d\u0433\u043e\u0432\u044b\u0435 \u0443\u0437\u043b\u044b \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u044e\u0442\u0441\u044f \u0434\u0440\u0443\u0433 \u043a \u0434\u0440\u0443\u0433\u0443)\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/43d\/908\/e6f\/43d908e6f14b60294b8bb69b5e8ad600.png\"\/><\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u043e\u0440\u0433\u0430\u043d\u0438\u0447\u043d\u043e \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u043b\u0441\u044f \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 20 \u043b\u0435\u0442, \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043b\u044e\u0434\u0438 \u0438 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0442\u0430\u043a\u0438\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u043a\u0430\u043a \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0435 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u044b \u0438 \u043d\u043e\u0432\u044b\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u044b \u043f\u043e\u0438\u0441\u043a\u0430 \u043e\u0434\u043d\u043e\u0440\u0430\u043d\u0433\u043e\u0432\u044b\u0445 \u0443\u0437\u043b\u043e\u0432. \u0427\u0442\u043e\u0431\u044b \u0443\u043f\u0440\u0430\u0432\u0438\u0442\u044c\u0441\u044f \u0437\u0430 \u0432\u044b\u0445\u043e\u0434\u043d\u044b\u0435, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c <a href=\"https:\/\/www.bittorrent.org\/beps\/bep_0003.html\">\u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u0443\u044e \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e<\/a> 2001 \u0433\u043e\u0434\u0430.<\/p>\n<p>  <\/p>\n<p>\u042f \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0441\u044c <a href=\"https:\/\/cdimage.debian.org\/debian-cd\/current\/amd64\/bt-cd\/#indexlist\">Debian ISO<\/a>, 350 \u041c\u0411. \u042d\u0442\u043e \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0439 \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0442\u0438\u0432 Linux, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0431\u044b\u0441\u0442\u0440\u044b\u0445 \u0438 \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0445 \u043e\u0434\u043d\u043e\u0440\u0430\u043d\u0433\u043e\u0432\u044b\u0445 \u0443\u0437\u043b\u043e\u0432, \u043a \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f. \u041f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u0442\u0430\u043a\u0436\u0435 \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u044e\u0440\u0438\u0434\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0438 \u044d\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043f\u0440\u043e\u0431\u043b\u0435\u043c, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u0441 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u043e\u0439 \u043f\u0438\u0440\u0430\u0442\u0441\u043a\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430.<\/p>\n<p>  <\/p>\n<h2 id=\"poisk-pirov\">\u041f\u043e\u0438\u0441\u043a \u043f\u0438\u0440\u043e\u0432<\/h2>\n<p>  <\/p>\n<p>\u0412\u043e\u0442 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430: \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0444\u0430\u0439\u043b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e BitTorrent, \u043d\u043e \u044d\u0442\u043e \u043e\u0434\u043d\u043e\u0440\u0430\u043d\u0433\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b, \u0438 \u043c\u044b \u043f\u043e\u043d\u044f\u0442\u0438\u044f \u043d\u0435 \u0438\u043c\u0435\u0435\u043c, \u0433\u0434\u0435 \u043d\u0430\u0439\u0442\u0438 \u043e\u0434\u043d\u043e\u0440\u0430\u043d\u0433\u043e\u0432\u044b\u0435 \u0443\u0437\u043b\u044b \u0434\u043b\u044f \u0435\u0433\u043e \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438. \u042d\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u0445\u043e\u0436\u0435 \u043d\u0430 \u043f\u0435\u0440\u0435\u0435\u0437\u0434 \u0432 \u043d\u043e\u0432\u044b\u0439 \u0433\u043e\u0440\u043e\u0434 \u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0443 \u0437\u0430\u0432\u0435\u0441\u0442\u0438 \u0434\u0440\u0443\u0437\u0435\u0439 \u2014 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c, \u043c\u044b \u0437\u0430\u0439\u0434\u0451\u043c \u0432 \u043c\u0435\u0441\u0442\u043d\u044b\u0439 \u043f\u0430\u0431 \u0438\u043b\u0438 \u0432\u0441\u0442\u0440\u0435\u0442\u0438\u043c\u0441\u044f! \u0426\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043c\u0435\u0441\u0442\u043e\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u2014 \u0433\u043b\u0430\u0432\u043d\u0430\u044f \u0438\u0434\u0435\u044f <strong>\u0442\u0440\u0435\u043a\u0435\u0440\u043e\u0432<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0441\u043e\u0431\u043e\u0439 \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u044b, \u0437\u043d\u0430\u043a\u043e\u043c\u044f\u0449\u0438\u0435 \u043e\u0434\u043d\u043e\u0440\u0430\u043d\u0433\u043e\u0432\u044b\u0435 \u0443\u0437\u043b\u044b \u0434\u0440\u0443\u0433 \u0441 \u0434\u0440\u0443\u0433\u043e\u043c. \u042d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u0435\u0431-\u0441\u0435\u0440\u0432\u0435\u0440\u044b, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0435 \u043f\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 HTTP. \u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0442\u0440\u0435\u043a\u0435\u0440\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 <a href=\"http:\/\/bittorrent.org\/beps\/bep_0015.html\">UDP<\/a> \u2014 \u0434\u0432\u043e\u0438\u0447\u043d\u044b\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0434\u043b\u044f \u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0438 \u043f\u043e\u043b\u043e\u0441\u044b \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/d6c\/05c\/c31\/d6c05cc31b9d37839c6152b22461d7ec.png\" alt=\"\u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043d\u0430\u0441\u0442\u043e\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0430 \u0438 \u043d\u043e\u0443\u0442\u0431\u0443\u043a\u0430, \u0441\u0438\u0434\u044f\u0449\u0438\u0445 \u0432 \u043f\u0430\u0431\u0435\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/d6c\/05c\/c31\/d6c05cc31b9d37839c6152b22461d7ec.png\"\/><\/p>\n<p>  <\/p>\n<p>\u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u044d\u0442\u0438 \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u044b \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u0434\u0432\u0435\u0440\u0433\u043d\u0443\u0442\u044c\u0441\u044f \u0440\u0435\u0439\u0434\u0443 \u0444\u0435\u0434\u0435\u0440\u0430\u043b\u043e\u0432, \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u0441\u043f\u043e\u0441\u043e\u0431\u0441\u0442\u0432\u0443\u044e\u0442 \u043e\u0431\u043c\u0435\u043d\u0443 \u043d\u0435\u0437\u0430\u043a\u043e\u043d\u043d\u044b\u043c \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u043e\u043c. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0432\u044b \u0447\u0438\u0442\u0430\u043b\u0438 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0442\u0430\u043a\u0438\u0435 \u0442\u0440\u0435\u043a\u0435\u0440\u044b, \u043a\u0430\u043a TorrentSpy, Popcorn Time \u0438 KickassTorrents, \u0437\u0430\u043a\u0440\u044b\u0442\u044b. \u041d\u043e\u0432\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0443\u0441\u0442\u0440\u0430\u043d\u044f\u044e\u0442 \u043f\u043e\u0441\u0440\u0435\u0434\u043d\u0438\u043a\u043e\u0432, \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u044f \u0432 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0434\u0430\u0436\u0435 <strong>\u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u043e\u0434\u043d\u043e\u0440\u0430\u043d\u0433\u043e\u0432\u044b\u0445 \u0443\u0437\u043b\u043e\u0432<\/strong>. \u041c\u044b \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u0438\u0445 \u0432\u043d\u0435\u0434\u0440\u044f\u0442\u044c, \u043d\u043e \u0435\u0441\u043b\u0438 \u0432\u0430\u043c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0442\u0435\u0440\u043c\u0438\u043d\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0437\u0443\u0447\u0438\u0442\u044c, \u2014 <strong>DHT<\/strong>, <strong>PEX<\/strong> \u0438 <strong>\u043c\u0430\u0433\u043d\u0438\u0442\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438<\/strong>.<\/p>\n<p>  <\/p>\n<h2 id=\"razbor-fayla-torrent\">\u0420\u0430\u0437\u0431\u043e\u0440 \u0444\u0430\u0439\u043b\u0430 .torrent<\/h2>\n<p>  <\/p>\n<p>\u0424\u0430\u0439\u043b .torrent \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0444\u0430\u0439\u043b\u0430, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0433\u043e \u0434\u043b\u044f \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430, \u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a \u0442\u0440\u0435\u043a\u0435\u0440\u0443. \u042d\u0442\u043e \u0432\u0441\u0451 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0435, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u0430. \u0422\u043e\u0440\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b Debian \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">d8:announce41:http:\/\/bttracker.debian.org:6969\/announce7:comment35:\"Debian CD from cdimage.debian.org\"13:creation datei1573903810e9:httpseedsl145:https:\/\/cdimage.debian.org\/cdimage\/release\/10.2.0\/\/srv\/cdbuilder.debian.org\/dst\/deb-cd\/weekly-builds\/amd64\/iso-cd\/debian-10.2.0-amd64-netinst.iso145:https:\/\/cdimage.debian.org\/cdimage\/archive\/10.2.0\/\/srv\/cdbuilder.debian.org\/dst\/deb-cd\/weekly-builds\/amd64\/iso-cd\/debian-10.2.0-amd64-netinst.isoe4:infod6:lengthi351272960e4:name31:debian-10.2.0-amd64-netinst.iso12:piece lengthi262144e6:pieces26800:PS^ (binary blob of the hashes of each piece)ee<\/code><\/pre>\n<p>  <\/p>\n<p>\u042d\u0442\u043e\u0442 \u0431\u0435\u0441\u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0437\u0430\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 <strong>Bencode<\/strong> (\u043f\u0440\u043e\u0438\u0437\u043d\u043e\u0441\u0438\u0442\u0441\u044f <em>bee-encode<\/em>), \u0438 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e.<\/p>\n<p>  <\/p>\n<p>Bencode \u043c\u043e\u0436\u0435\u0442 \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0435 \u0436\u0435 \u0442\u0438\u043f\u044b \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440, \u0447\u0442\u043e \u0438 JSON \u2014 \u0441\u0442\u0440\u043e\u043a\u0438, \u0446\u0435\u043b\u044b\u0435 \u0447\u0438\u0441\u043b\u0430, \u0441\u043f\u0438\u0441\u043a\u0438 \u0438 \u0441\u043b\u043e\u0432\u0430\u0440\u0438. \u0417\u0430\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 bencode \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0435 \u0442\u0430\u043a \u0443\u0434\u043e\u0431\u043d\u044b \u0434\u043b\u044f \u0447\u0442\u0435\u043d\u0438\u044f \/ \u0437\u0430\u043f\u0438\u0441\u0438 \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u043e\u043c, \u043a\u0430\u043a JSON, \u043d\u043e \u043e\u043d\u0438 \u043c\u043e\u0433\u0443\u0442 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0434\u0432\u043e\u0438\u0447\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u0438 \u0438\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0437 \u043f\u043e\u0442\u043e\u043a\u0430. \u0421\u0442\u0440\u043e\u043a\u0438 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0441 \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u043e\u043c \u0434\u043b\u0438\u043d\u044b \u0438 \u0432\u044b\u0433\u043b\u044f\u0434\u044f\u0442 \u043a\u0430\u043a <code>4:spam<\/code>. \u0426\u0435\u043b\u044b\u0435 \u0447\u0438\u0441\u043b\u0430 \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u044e\u0442\u0441\u044f \u043c\u0435\u0436\u0434\u0443 \u043c\u0430\u0440\u043a\u0435\u0440\u0430\u043c\u0438 <em>start<\/em> \u0438 <em>end<\/em>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 <code>7<\/code> \u043a\u043e\u0434\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043a\u0430\u043a <code>i7e<\/code>. \u0421\u043f\u0438\u0441\u043a\u0438 \u0438 \u0441\u043b\u043e\u0432\u0430\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c: <code>l4:spami7ee<\/code> \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 <code>['spam', 7]<\/code>, \u0442\u043e\u0433\u0434\u0430 \u043a\u0430\u043a <code>d4:spami7ee<\/code> \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 <code>{spam: 7}<\/code>.<\/p>\n<p>  <\/p>\n<p>\u0412 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 \u043f\u043e\u043a\u0440\u0430\u0441\u0438\u0432\u0435\u0435 .torrent \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">d   8:announce     41:http:\/\/bttracker.debian.org:6969\/announce   7:comment     35:\"Debian CD from cdimage.debian.org\"   13:creation date     i1573903810e   4:info     d       6:length         i351272960e       4:name         31:debian-10.2.0-amd64-netinst.iso       12:piece length         i262144e       6:pieces         26800:PS^ (binary blob of the hashes of each piece)<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e \u044d\u0442\u043e\u043c\u0443 \u0444\u0430\u0439\u043b\u0443 \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u0441\u043b\u0435\u0434\u0438\u0442\u044c URL \u0442\u0440\u0435\u043a\u0435\u0440\u0430, \u0434\u0430\u0442\u0443 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f (\u0432 \u0432\u0438\u0434\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043c\u0435\u0442\u043a\u0438 Unix), \u0438\u043c\u044f \u0438 \u0440\u0430\u0437\u043c\u0435\u0440 \u0444\u0430\u0439\u043b\u0430. \u041a\u0440\u043e\u043c\u0435 \u044d\u0442\u043e\u0433\u043e, \u0432 \u0444\u0430\u0439\u043b\u0435 \u0435\u0441\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0431\u0438\u043d\u0430\u0440\u043d\u044b\u0439 \u0431\u043b\u043e\u0431, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c\u0441\u044f SHA-1 \u0445\u044d\u0448\u0438 \u043a\u0430\u0436\u0434\u043e\u0439 <strong>\u0447\u0430\u0441\u0442\u0438 \u0444\u0430\u0439\u043b\u0430<\/strong>. \u042d\u0442\u0438 \u0447\u0430\u0441\u0442\u0438 \u0440\u0430\u0432\u043d\u044b \u043f\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0443 \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 \u0444\u0430\u0439\u043b\u0430 \u0434\u043b\u044f \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f. \u0423 \u0440\u0430\u0437\u043d\u044b\u0445 \u0442\u043e\u0440\u0440\u0435\u043d\u0442\u043e\u0432 \u0440\u0430\u0437\u043c\u0435\u0440 \u0447\u0430\u0441\u0442\u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u043c, \u043d\u043e \u043e\u0431\u044b\u0447\u043d\u043e \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 \u043e\u0442 256 \u041a\u0411 \u0434\u043e 1 \u041c\u0411. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043a\u0440\u0443\u043f\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u0442\u044c \u0438\u0437 <em>\u0442\u044b\u0441\u044f\u0447<\/em> \u0447\u0430\u0441\u0442\u0435\u0439. \u042d\u0442\u0438 \u0447\u0430\u0441\u0442\u0438 \u043c\u044b \u0441\u043a\u0430\u0447\u0430\u0435\u043c \u0443 \u043f\u0438\u0440\u043e\u0432, \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u0438\u0445 \u043f\u043e \u0445\u044d\u0448\u0430\u043c \u043d\u0430\u0448\u0435\u0433\u043e \u0442\u043e\u0440\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b\u0430 \u0438 \u0441\u043e\u0431\u0435\u0440\u0451\u043c \u0438\u0445 \u0432\u043e\u0435\u0434\u0438\u043d\u043e. \u0412\u0441\u0451. \u0424\u0430\u0439\u043b \u0433\u043e\u0442\u043e\u0432!<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/c7c\/902\/dcc\/c7c902dcce4dd1ecf320979b4ea27fec.png\" alt=\"\u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430, \u0440\u0430\u0437\u0440\u0435\u0437\u0430\u0435\u043c\u043e\u0433\u043e \u043d\u043e\u0436\u043d\u0438\u0446\u0430\u043c\u0438 \u043d\u0430 \u0447\u0430\u0441\u0442\u0438, \u043f\u0440\u043e\u043d\u0443\u043c\u0435\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0441 piece 0\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/c7c\/902\/dcc\/c7c902dcce4dd1ecf320979b4ea27fec.png\"\/><\/p>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u043e\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u0446\u0435\u043b\u043e\u0441\u0442\u043d\u043e\u0441\u0442\u044c \u043a\u0430\u0436\u0434\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0444\u0430\u0439\u043b\u0430 \u0432 \u0445\u043e\u0434\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c, BitTorrent \u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432 \u043a \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u043c\u0443 \u0438 \u043d\u0430\u043c\u0435\u0440\u0435\u043d\u043d\u043e\u043c\u0443 \u043f\u043e\u0432\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u044e \u0442\u043e\u0440\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b\u0430 <strong>(torrent poisoning)<\/strong>. \u0415\u0441\u043b\u0438 \u0445\u0430\u043a\u0435\u0440\u0443 \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0432\u0437\u043b\u043e\u043c\u0430\u0442\u044c SHA-1 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0430\u0442\u0430\u043a\u0438 \u043f\u0440\u0430\u043e\u0431\u0440\u0430\u0437\u0430 (preimage attack), \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0440\u043e\u0432\u043d\u043e \u0442\u043e\u0442 \u043a\u043e\u043d\u0442\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441\u0438\u043b\u0438.<\/p>\n<p>  <\/p>\n<p>\u0417\u0434\u043e\u0440\u043e\u0432\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u0439 bencode-\u043f\u0430\u0440\u0441\u0435\u0440, \u043d\u043e \u0441\u0442\u0430\u0442\u044c\u044f \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u0430 \u043d\u0435 \u043f\u0430\u0440\u0441\u0435\u0440\u0430\u043c. <a href=\"https:\/\/web.archive.org\/web\/20200105114449\/https:\/\/effbot.org\/zone\/bencode.htm\">\u041f\u0430\u0440\u0441\u0435\u0440 \u043d\u0430 50 \u0441\u0442\u0440\u043e\u043a \u043a\u043e\u0434\u0430<\/a> \u043e\u0442 \u0424\u0440\u0435\u0434\u0435\u0440\u0438\u043a\u0430 \u041b\u0443\u043d\u0434\u0430 \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u043c\u043d\u0435 \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u043c. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0441\u044f <a href=\"https:\/\/github.com\/jackpal\/bencode-go\">github.com\/jackpal\/bencode-go<\/a>:<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">import (     \"github.com\/jackpal\/bencode-go\" )  type bencodeInfo struct {     Pieces      string `bencode:\"pieces\"`     PieceLength int    `bencode:\"piece length\"`     Length      int    `bencode:\"length\"`     Name        string `bencode:\"name\"` }  type bencodeTorrent struct {     Announce string      `bencode:\"announce\"`     Info     bencodeInfo `bencode:\"info\"` }  \/\/ Open parses a torrent file func Open(r io.Reader) (*bencodeTorrent, error) {     bto := bencodeTorrent{}     err := bencode.Unmarshal(r, &amp;bto)     if err != nil {         return nil, err     }     return &amp;bto, nil }<\/code><\/pre>\n<p>  <\/p>\n<p><a href=\"https:\/\/github.com\/veggiedefender\/torrent-client\/blob\/2bde944888e1195e81cc5d5b686f6ec3a9f08c25\/torrentfile\/torrentfile.go\">\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435<\/a><\/p>\n<p>  <\/p>\n<p>\u041c\u043d\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043b\u043e\u0441\u043a\u0438\u043c\u0438 \u0438 \u043e\u0442\u0434\u0435\u043b\u044f\u0442\u044c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043e\u0442 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 (serialization structs). \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043b \u0434\u0440\u0443\u0433\u0443\u044e, \u0431\u043e\u043b\u0435\u0435 \u043f\u043b\u043e\u0441\u043a\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 <code>TorrentFile<\/code> \u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0434\u043b\u044f \u0438\u0445 \u0432\u0437\u0430\u0438\u043c\u043e\u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e <code>pieces<\/code> (\u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e, \u044d\u0442\u043e \u0431\u044b\u043b\u0430 \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u0430\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f) \u044f \u0440\u0430\u0437\u0431\u0438\u043b \u043d\u0430 \u0445\u044d\u0448-\u0441\u043b\u0430\u0439\u0441\u044b (slice of hashes) \u043f\u043e <code>[20] \u0431\u0430\u0439\u0442<\/code> \u043d\u0430 \u0445\u044d\u0448. \u042d\u0442\u043e \u0443\u043f\u0440\u043e\u0441\u0438\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u0443 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c \u0445\u044d\u0448\u0430\u043c. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u044f \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u043b \u043e\u0431\u0449\u0438\u0439 \u0445\u044d\u0448 SHA-1 \u0432\u0441\u0435\u0433\u043e \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0432 bencode \u0441\u043b\u043e\u0432\u0430\u0440\u044f <code>info<\/code> (\u0433\u0434\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u0441\u044f \u0438\u043c\u044f, \u0440\u0430\u0437\u043c\u0435\u0440 \u0438 \u0445\u044d\u0448 \u043a\u0430\u0436\u0434\u043e\u0439 \u0447\u0430\u0441\u0442\u0438). \u042d\u0442\u043e\u0442 \u0445\u044d\u0448 \u0438\u0437\u0432\u0435\u0441\u0442\u0435\u043d \u043d\u0430\u043c \u043a\u0430\u043a <strong>\u0438\u043d\u0444\u043e\u0445\u044d\u0448 (infohash)<\/strong>, \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0444\u0430\u0439\u043b\u043e\u0432 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0442\u0440\u0435\u043a\u0435\u0440\u0430\u043c \u0438 \u043f\u0438\u0440\u0430\u043c. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e\u0431 \u044d\u0442\u043e\u043c \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c \u043f\u043e\u0437\u0436\u0435.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/1cd\/93b\/a53\/1cd93ba53dc2a87d238ea352a4938617.png\" alt=\"\u0438\u043c\u0435\u043d\u043d\u0430\u044f \u0442\u0430\u0431\u043b\u0438\u0447\u043a\u0430 'Hello my name is 86d4c80024a469be4c50bc5a102cf71780310074'\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/1cd\/93b\/a53\/1cd93ba53dc2a87d238ea352a4938617.png\"\/><\/p>\n<p>  <\/p>\n<pre><code class=\"go\">type TorrentFile struct {     Announce    string     InfoHash    [20]byte     PieceHashes [][20]byte     PieceLength int     Length      int     Name        string }<\/code><\/pre>\n<p>  <\/p>\n<p><a href=\"https:\/\/github.com\/veggiedefender\/torrent-client\/blob\/2bde944888e1195e81cc5d5b686f6ec3a9f08c25\/torrentfile\/torrentfile.go#L120-L138\">\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435<\/a><\/p>\n<p>  <\/p>\n<h2 id=\"poluchenie-pirov-cherez-treker\">\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043f\u0438\u0440\u043e\u0432 \u0447\u0435\u0440\u0435\u0437 \u0442\u0440\u0435\u043a\u0435\u0440<\/h2>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u0438\u043c\u0435\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0444\u0430\u0439\u043b\u0435 \u0438 \u0435\u0433\u043e \u0442\u0440\u0435\u043a\u0435\u0440\u0435, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u0431\u0440\u0430\u0442\u0438\u043c\u0441\u044f \u043a \u0442\u0440\u0435\u043a\u0435\u0440\u0443 \u0434\u043b\u044f <strong>\u0430\u043d\u043e\u043d\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f<\/strong> \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u044f \u0441\u0440\u0435\u0434\u0438 \u043f\u0438\u0440\u043e\u0432 \u0438 \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u043f\u0438\u0441\u043a\u0430 \u0434\u0440\u0443\u0433\u0438\u0445 \u043f\u0438\u0440\u043e\u0432. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 GET \u043d\u0430 URL <code>announce<\/code> \u0432 \u0444\u0430\u0439\u043b\u0435 .torrent \u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">func (t *TorrentFile) buildTrackerURL(peerID [20]byte, port uint16) (string, error) {     base, err := url.Parse(t.Announce)     if err != nil {         return \"\", err     }     params := url.Values{         \"info_hash\":  []string{string(t.InfoHash[:])},         \"peer_id\":    []string{string(peerID[:])},         \"port\":       []string{strconv.Itoa(int(Port))},         \"uploaded\":   []string{\"0\"},         \"downloaded\": []string{\"0\"},         \"compact\":    []string{\"1\"},         \"left\":       []string{strconv.Itoa(t.Length)},     }     base.RawQuery = params.Encode()     return base.String(), nil }<\/code><\/pre>\n<p>  <\/p>\n<p><a href=\"https:\/\/github.com\/veggiedefender\/torrent-client\/blob\/2bde944888e1195e81cc5d5b686f6ec3a9f08c25\/torrentfile\/tracker.go#L19-L35\">\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435<\/a><\/p>\n<p>  <\/p>\n<p>\u0412\u0430\u0436\u043d\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u043a\u043e\u0434\u0430:<\/p>\n<p>  <\/p>\n<ul>\n<li><strong>info_hash<\/strong>: \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u0442 <em>\u0444\u0430\u0439\u043b<\/em>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0441\u043a\u0430\u0447\u0430\u0442\u044c. \u042d\u0442\u043e \u0438\u043d\u0444\u043e\u0445\u044d\u0448 (infohash), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u043b\u0438 \u0440\u0430\u043d\u0435\u0435 \u043f\u043e \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c\u0443 bencode \u0441\u043b\u043e\u0432\u0430\u0440\u044e <code>info<\/code>. \u0422\u0440\u0435\u043a\u0435\u0440\u0443 \u043d\u0443\u0436\u043d\u043e \u0437\u043d\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u0445\u044d\u0448, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043d\u0430\u043c \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u0435\u0445 \u043f\u0438\u0440\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0443\u0436\u043d\u044b.<\/li>\n<li><strong>peer_id<\/strong>: \u0438\u043c\u044f \u043d\u0430 20 \u0431\u0430\u0439\u0442, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u0442 <em>\u043d\u0430\u0441<\/em> \u043d\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u0430\u0445 \u0438 \u0434\u043b\u044f \u043f\u0438\u0440\u043e\u0432. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0431\u0435\u0440\u0451\u043c 20 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0445 \u0431\u0430\u0439\u0442\u043e\u0432. \u0420\u0435\u0430\u043b\u044c\u043d\u044b\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u044b BitTorrent \u0438\u043c\u0435\u044e\u0442 ID \u0432\u0438\u0434\u0430 <code>-TR2940-k8hj0wgej6ch<\/code>, \u0433\u0434\u0435 \u0437\u0430\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0435 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u0435 \u0438 \u0435\u0433\u043e \u0432\u0435\u0440\u0441\u0438\u044f. \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 TR2940 \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 Transmission client 2.94.<\/li>\n<\/ul>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/f2e\/ab5\/125\/f2eab51258ae0a89a8da03302f7c76d5.png\" alt=\"\u0444\u0430\u0439\u043b \u0441 \u0438\u043c\u0435\u043d\u043d\u043e\u0439 \u0442\u0430\u0431\u043b\u0438\u0447\u043d\u043e\u0439 'info_hash' \u0438 \u0447\u0435\u043b\u043e\u0432\u0435\u0447\u0435\u043a \u0441 \u0438\u043c\u0435\u043d\u043d\u043e\u0439 \u0442\u0430\u0431\u043b\u0438\u0447\u043a\u043e\u0439 'peer_id'\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/f2e\/ab5\/125\/f2eab51258ae0a89a8da03302f7c76d5.png\"\/><\/p>\n<p>  <\/p>\n<h2 id=\"httpsblogjselipoststorrentparsing-the-tracker-responseparsing-otveta-trekera\"><a href=\"https:\/\/blog.jse.li\/posts\/torrent\/\/#parsing-the-tracker-response\">##<\/a>\u041f\u0430\u0440\u0441\u0438\u043d\u0433 \u043e\u0442\u0432\u0435\u0442\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u0430<\/h2>\n<p>  <\/p>\n<p>\u041c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043e\u0442\u0432\u0435\u0442, \u0437\u0430\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 bencode:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">d   8:interval     i900e   5:peers     252:(another long binary blob) e<\/code><\/pre>\n<p>  <\/p>\n<p><code>interval<\/code> \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043a\u0430\u043a \u0447\u0430\u0441\u0442\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0434\u0435\u043b\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u043f\u0438\u0441\u043a\u0430 \u043f\u0438\u0440\u043e\u0432. \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 900 \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0435\u0440\u0435\u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c\u0441\u044f \u0440\u0430\u0437 \u0432 15 \u043c\u0438\u043d\u0443\u0442 (900 \u0441\u0435\u043a\u0443\u043d\u0434).<\/p>\n<p>  <\/p>\n<p><code>peers<\/code> \u2014 \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0431\u0438\u043d\u0430\u0440\u043d\u044b\u0439 \u0431\u043b\u043e\u0431, \u0433\u0434\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u0441\u044f IP-\u0430\u0434\u0440\u0435\u0441\u0430 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u0438\u0440\u0430. \u041e\u043d \u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d <strong>\u0433\u0440\u0443\u043f\u043f\u0430\u043c\u0438 \u043f\u043e 6 \u0431\u0430\u0439\u0442\u043e\u0432<\/strong>. \u041f\u0435\u0440\u0432\u044b\u0435 4 \u0431\u0430\u0439\u0442\u0430 \u2014 \u044d\u0442\u043e IP \u0430\u0434\u0440\u0435\u0441 \u043f\u0438\u0440\u0430, \u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0431\u0430\u0439\u0442 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0447\u0438\u0441\u043b\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 IP. \u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 2 \u0431\u0430\u0439\u0442\u0430 \u2014 \u043f\u043e\u0440\u0442, \u0432 \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0435 big-endian \u044d\u0442\u043e <code>uint16<\/code>. <strong>Big-endian<\/strong> \u0438\u043b\u0438 <strong>\u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u043f\u043e\u0440\u044f\u0434\u043e\u043a (network order)<\/strong> \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442, \u0447\u0442\u043e \u0433\u0440\u0443\u043f\u043f\u0443 \u0431\u0430\u0439\u0442\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0432 \u0432\u0438\u0434\u0435 \u0446\u0435\u043b\u043e\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u0434\u0432\u0438\u0433\u0430\u044f\u0441\u044c \u043f\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0443 \u0441\u043b\u0435\u0432\u0430 \u043d\u0430\u043f\u0440\u0430\u0432\u043e. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0431\u0430\u0439\u0442\u044b <code>0x1A<\/code>, <code>0xE1<\/code> \u043a\u043e\u0434\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0432 <code>0x1AE1<\/code> \u0438\u043b\u0438 6881 \u0432 \u0434\u0435\u0441\u044f\u0442\u0438\u0447\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435.*\u0418\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0446\u0438\u044f \u0442\u0435\u0445 \u0436\u0435 \u0431\u0430\u0439\u0442\u043e\u0432 \u0432 \u043f\u043e\u0440\u044f\u0434\u043a\u0435 <strong>little-endian<\/strong> \u0434\u0430\u043b\u0430 \u0431\u044b 0xE11A = 57626<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/00f\/6b8\/e8a\/00f6b8e8a096f031d0293dc787e267b0.png\" alt=\"\u0441\u0445\u0435\u043c\u0430 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0446\u0438\u0438 192, 0, 2, 123, 0x1A, 0xE1 \u0432 \u0432\u0438\u0434\u0435 192.0.1.123:6881\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/00f\/6b8\/e8a\/00f6b8e8a096f031d0293dc787e267b0.png\"\/><\/p>\n<p>  <\/p>\n<pre><code class=\"go\">\/\/ Peer encodes connection information for a peer type Peer struct {     IP   net.IP     Port uint16 }  \/\/ Unmarshal parses peer IP addresses and ports from a buffer func Unmarshal(peersBin []byte) ([]Peer, error) {     const peerSize = 6 \/\/ 4 for IP, 2 for port     numPeers := len(peersBin) \/ peerSize     if len(peersBin)%peerSize != 0 {         err := fmt.Errorf(\"Received malformed peers\")         return nil, err     }     peers := make([]Peer, numPeers)     for i := 0; i &lt; numPeers; i++ {         offset := i * peerSize         peers[i].IP = net.IP(peersBin[offset : offset+4])         peers[i].Port = binary.BigEndian.Uint16(peersBin[offset+4 : offset+6])     }     return peers, nil }<\/code><\/pre>\n<p>  <\/p>\n<p><a href=\"https:\/\/github.com\/veggiedefender\/torrent-client\/blob\/2bde944888e1195e81cc5d5b686f6ec3a9f08c25\/peers\/peers.go\">\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435<\/a><\/p>\n<p>  <\/p>\n<h1 id=\"skachivanie-u-pirov\">\u0421\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u0435 \u0443 \u043f\u0438\u0440\u043e\u0432<\/h1>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u0438\u043c\u0435\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u0438\u0440\u043e\u0432, \u043f\u043e\u0440\u0430 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f \u043a \u043d\u0438\u043c \u0438 \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b \u0447\u0430\u0441\u0442\u044f\u043c\u0438! \u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u0438\u0440\u0430 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<p>  <\/p>\n<ol>\n<li>\u041d\u0430\u0447\u0430\u043b\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a \u043f\u0438\u0440\u0443 \u043f\u043e TCP. \u042d\u0442\u043e \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e, \u0447\u0442\u043e \u0441\u043d\u044f\u0442\u044c \u0442\u0440\u0443\u0431\u043a\u0443 \u0438 \u043d\u0430\u0431\u0440\u0430\u0442\u044c \u043d\u043e\u043c\u0435\u0440.<\/li>\n<li>\u0414\u0432\u0443\u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0435\u0435 BitTorrent-<strong>\u0440\u0443\u043a\u043e\u043f\u043e\u0436\u0430\u0442\u0438\u0435<\/strong>. \u042d\u0442\u043e \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e, \u0447\u0442\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c <em>\u00ab\u0410\u043b\u043b\u043e\u00bb<\/em> \u0438 \u0443\u0441\u043b\u044b\u0448\u0430\u0442\u044c <em>\u00ab\u0410\u043b\u043b\u043e\u00bb<\/em> \u0432 \u043e\u0442\u0432\u0435\u0442.<\/li>\n<li>\u041e\u0431\u043c\u0435\u043d <strong>\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f\u043c\u0438 (messages)<\/strong> \u0434\u043b\u044f \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f <strong>\u0447\u0430\u0441\u0442\u0435\u0439<\/strong> \u0444\u0430\u0439\u043b\u0430. <em>\u00ab\u041c\u043d\u0435, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, 231-\u044e \u0447\u0430\u0441\u0442\u044c\u00bb.<\/em><\/li>\n<\/ol>\n<p>  <\/p>\n<h2 id=\"nachalo-podklyucheniya-po-tcp\">\u041d\u0430\u0447\u0430\u043b\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043f\u043e TCP<\/h2>\n<p>  <\/p>\n<pre><code class=\"go\">conn, err := net.DialTimeout(\"tcp\", peer.String(), 3*time.Second) if err != nil {     return nil, err }<\/code><\/pre>\n<p>  <\/p>\n<p><a href=\"https:\/\/github.com\/veggiedefender\/torrent-client\/blob\/2bde944888e1195e81cc5d5b686f6ec3a9f08c25\/client\/client.go#L65-L69\">\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435<\/a><\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u044f \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0441\u044f \u0442\u0430\u0439\u043c\u0430\u0443\u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0442\u0435\u0440\u044f\u0442\u044c \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043d\u0430 \u043f\u0438\u0440\u0430\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0434\u0430\u044e\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f. \u0412 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0436\u0435 \u044d\u0442\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438 \u043f\u043e TCP.<\/p>\n<p>  <\/p>\n<h2 id=\"httpsblogjselipoststorrentcomplete-the-handshakehendsheyk\"><a href=\"https:\/\/blog.jse.li\/posts\/torrent\/\/#complete-the-handshake\">##<\/a>\u0425\u044d\u043d\u0434\u0448\u0435\u0439\u043a<\/h2>\n<p>  <\/p>\n<p>\u041c\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043b\u0438\u0441\u044c \u043a \u043f\u0438\u0440\u0443. \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0443\u0436\u043d\u043e \u0440\u0443\u043a\u043e\u043f\u043e\u0436\u0430\u0442\u0438\u0435, \u0447\u0442\u043e\u0431\u044b \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u044d\u0442\u043e\u0442 \u043f\u0438\u0440:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u043c\u043e\u0436\u0435\u0442 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u043f\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 BitTorrent;<\/li>\n<li>\u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c \u043d\u0430\u0448\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0438 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u043d\u0430 \u043d\u0438\u0445;<\/li>\n<li>\u0438\u043c\u0435\u0435\u0442 \u043d\u0443\u0436\u043d\u044b\u0439 \u043d\u0430\u043c \u0444\u0430\u0439\u043b, \u0438\u043b\u0438 \u0445\u043e\u0442\u044f \u0431\u044b \u0437\u043d\u0430\u0435\u0442, \u043e \u0447\u0451\u043c \u0438\u0434\u0451\u0442 \u0440\u0435\u0447\u044c.<\/li>\n<\/ul>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/23e\/39f\/98c\/23e39f98c000d30486ded27d0c876fec.png\" alt=\"\u0414\u0432\u0430 \u043e\u0431\u0449\u0430\u044e\u0449\u0438\u0445\u0441\u044f \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0430. \u041e\u0434\u0438\u043d \u0441\u043f\u0440\u0430\u0432\u0438\u0432\u0430\u0435\u0442: 'do you speak BitTorrent and have this file?', \u0434\u0440\u0443\u0433\u043e\u0439 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442: 'I speak BitTorrent and have that file'\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/23e\/39f\/98c\/23e39f98c000d30486ded27d0c876fec.png\"\/><\/p>\n<p>  <\/p>\n<p>\u041a\u0430\u043a \u043d\u0435\u043a\u043e\u0433\u0434\u0430 \u0433\u043e\u0432\u043e\u0440\u0438\u043b \u043c\u043e\u0439 \u043e\u0442\u0435\u0446, \u0445\u043e\u0440\u043e\u0448\u0435\u0435 \u0440\u0443\u043a\u043e\u043f\u043e\u0436\u0430\u0442\u0438\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043a\u0440\u0435\u043f\u043a\u0438\u043c \u0438 \u0441 \u043a\u043e\u043d\u0442\u0430\u043a\u0442\u043e\u043c \u0433\u043b\u0430\u0437\u0430\u043c\u0438, \u0432 \u044d\u0442\u043e\u043c \u0438 \u0432\u0435\u0441\u044c \u0441\u0435\u043a\u0440\u0435\u0442. \u0412 BitTorrent \u0436\u0435 \u0441\u0435\u043a\u0440\u0435\u0442 \u0445\u043e\u0440\u043e\u0448\u0435\u0433\u043e \u00ab\u0440\u0443\u043a\u043e\u043f\u043e\u0436\u0430\u0442\u0438\u044f\u00bb \u2014 \u0438\u043b\u0438 \u0445\u044d\u043d\u0434\u0448\u0435\u0439\u043a\u0430 \u2014 \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 5 \u0430\u0441\u043f\u0435\u043a\u0442\u043e\u0432:<\/p>\n<p>  <\/p>\n<ol>\n<li>\u0414\u043b\u0438\u043d\u0430 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 \u0432\u0441\u0435\u0433\u0434\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0440\u0430\u0432\u043d\u0430 19 (0x13 \u0432 hex)<\/li>\n<li>\u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f <strong>pstr<\/strong>, \u2014 \u044d\u0442\u043e \u0432\u0441\u0435\u0433\u0434\u0430 \u0441\u0442\u0440\u043e\u043a\u0430 <code>BitTorrent protocol<\/code><\/li>\n<li>8 **\u0437\u0430\u0440\u0435\u0437\u0435\u0440\u0432\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0431\u0430\u0439\u0442\u043e\u0432, \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0445 \u0432 0. \u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0437 \u043d\u0438\u0445 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 1 \u0434\u043b\u044f \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 <a href=\"http:\/\/www.bittorrent.org\/beps\/bep_0010.html\">\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439 (extensions)<\/a>. \u0422\u0430\u043a \u043a\u0430\u043a \u044d\u0442\u043e\u0433\u043e \u043d\u0435 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e, \u043c\u044b \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0438\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 0.<\/li>\n<li><strong>\u0418\u043d\u0444\u043e\u0445\u044d\u0448 (infohash)<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u043b\u0438 \u0440\u0430\u043d\u0435\u0435 \u0434\u043b\u044f \u0436\u0435\u043b\u0430\u0435\u043c\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430<\/li>\n<li><strong>ID \u043f\u0438\u0440\u0430 (Peer ID)<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043c\u044b \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u0441\u0435\u0431\u044f<\/li>\n<\/ol>\n<p>  <\/p>\n<p>\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u044d\u0442\u043e \u0432\u0441\u0451 \u0432\u043c\u0435\u0441\u0442\u0435 \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0445\u044d\u043d\u0434\u0448\u0435\u0439\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">\\x13BitTorrent protocol\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x86\\xd4\\xc8\\x00\\x24\\xa4\\x69\\xbe\\x4c\\x50\\xbc\\x5a\\x10\\x2c\\xf7\\x17\\x80\\x31\\x00\\x74-TR2940-k8hj0wgej6ch<\/code><\/pre>\n<p>  <\/p>\n<p>\u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0432 \u0445\u044d\u043d\u0434\u0448\u0435\u0439\u043a \u043f\u0438\u0440\u0443, \u043c\u044b \u043e\u0436\u0438\u0434\u0430\u0435\u043c \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 \u0445\u044d\u043d\u0434\u0448\u0435\u0439\u043a \u0432 \u0442\u043e\u043c \u0436\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u0435. \u0418\u043d\u0444\u043e\u0445\u044d\u0448, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0432 \u043e\u0442\u0432\u0435\u0442\u0435, \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u043e\u0432\u043f\u0430\u0441\u0442\u044c \u0441 \u043d\u0430\u0448\u0438\u043c. \u0422\u043e\u0433\u0434\u0430 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u0433\u043e\u0432\u043e\u0440\u0438\u043c \u043e\u0431 \u043e\u0434\u043d\u043e\u043c \u0438 \u0442\u043e\u043c \u0436\u0435 \u0444\u0430\u0439\u043b\u0435. \u0415\u0441\u043b\u0438 \u0432\u0441\u0451 \u0438\u0434\u0451\u0442 \u043f\u043e \u043f\u043b\u0430\u043d\u0443, \u0435\u0434\u0435\u043c \u0434\u0430\u043b\u044c\u0448\u0435. \u0415\u0441\u043b\u0438 \u043d\u0435\u0442, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0440\u0430\u0437\u044a\u0435\u0434\u0438\u043d\u0438\u0442\u044c\u0441\u044f. <em>\u00ab\u0410\u043b\u043b\u043e\u00bb. \u00ab\u0427\u0436\u0435 \u0448\u0438 \u0448\u0435\u0439 \u041d\u0438\u043d \u0441\u044f\u043d \u044f\u043e \u0448\u0435\u043d\u044c\u043c\u0435\u00bb \u00ab\u041e\u0439, \u0438\u0437\u0432\u0438\u043d\u0438\u0442\u0435, \u043e\u0448\u0438\u0431\u0441\u044f \u043d\u043e\u043c\u0435\u0440\u043e\u043c\u00bb.<\/em><\/p>\n<p>  <\/p>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0432 \u043d\u0430\u0448\u0435\u043c \u043a\u043e\u0434\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0443\u044e \u0445\u044d\u043d\u0434\u0448\u0435\u0439\u043a, \u0438 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0434\u043b\u044f \u0438\u0445 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u0447\u0442\u0435\u043d\u0438\u044f:<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">\/\/ A Handshake is a special message that a peer uses to identify itself type Handshake struct {     Pstr     string     InfoHash [20]byte     PeerID   [20]byte }  \/\/ Serialize serializes the handshake to a buffer func (h *Handshake) Serialize() []byte {     buf := make([]byte, len(h.Pstr)+49)     buf[0] = byte(len(h.Pstr))     curr := 1     curr += copy(buf[curr:], h.Pstr)     curr += copy(buf[curr:], make([]byte, 8)) \/\/ 8 reserved bytes     curr += copy(buf[curr:], h.InfoHash[:])     curr += copy(buf[curr:], h.PeerID[:])     return buf }  \/\/ Read parses a handshake from a stream func Read(r io.Reader) (*Handshake, error) {     \/\/ Do Serialize(), but backwards     \/\/ ... }<\/code><\/pre>\n<p>  <\/p>\n<p><a href=\"https:\/\/github.com\/veggiedefender\/torrent-client\/blob\/a83013d250dd9b4268cceace28e4cd82b07f2cbd\/handshake\/handshake.go\">\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435<\/a><\/p>\n<p>  <\/p>\n<h2 id=\"otpravka-i-poluchenie-soobscheniy\">\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439<\/h2>\n<p>  <\/p>\n<p>\u041f\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0438 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0445\u044d\u043d\u0434\u0448\u0435\u0439\u043a\u0430 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0438 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c <strong>\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f<\/strong>. \u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u0435\u0441\u043b\u0438 \u0434\u0440\u0443\u0433\u043e\u0439 \u043f\u0438\u0440 \u043d\u0435 \u0433\u043e\u0442\u043e\u0432 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f, \u043c\u044b \u043d\u0435 \u0441\u043c\u043e\u0436\u0435\u043c \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c, \u043f\u043e\u043a\u0430 \u043e\u043d \u043d\u0435 \u0441\u043a\u0430\u0436\u0435\u0442, \u0447\u0442\u043e \u0433\u043e\u0442\u043e\u0432. \u0412 \u044d\u0442\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 \u043c\u044b, \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u043f\u0438\u0440\u0430, <strong>\u00ab\u0437\u0430\u0433\u043b\u0443\u0448\u0435\u043d\u044b\u00bb (choked)<\/strong>. \u041e\u043d\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043d\u0430\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 <strong>unchoke<\/strong>, \u0441\u043e\u043e\u0431\u0449\u0430\u044e\u0449\u0435\u0435, \u0447\u0442\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u043a \u0437\u0430\u043f\u0440\u043e\u0441\u0443 \u0434\u0430\u043d\u043d\u044b\u0445. \u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043c\u044b \u0441\u0447\u0438\u0442\u0430\u0435\u043c, \u0447\u0442\u043e \u0432\u0441\u0435\u0433\u0434\u0430 \u00ab\u0437\u0430\u0433\u043b\u0443\u0448\u0435\u043d\u044b\u00bb, \u043f\u043e\u043a\u0430 \u043d\u0435 \u0443\u0431\u0435\u0436\u0434\u0430\u0435\u043c\u0441\u044f \u0432 \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u043c.<\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u043b\u0443\u0447\u0438\u0432 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 unchoked, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u043a \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 <strong>\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 (requests)<\/strong> \u043d\u0430 \u0447\u0430\u0441\u0442\u0438 \u0444\u0430\u0439\u043b\u0430, \u0430 \u043e\u043d\u0438 \u2014 \u043f\u0440\u0438\u0441\u044b\u043b\u0430\u0442\u044c \u0432 \u043e\u0442\u0432\u0435\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0441 \u0442\u0430\u043a\u0438\u043c\u0438 \u0447\u0430\u0441\u0442\u044f\u043c\u0438.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/54f\/bd6\/857\/54fbd685754d1b3c2af1f5ad15d51c09.png\" alt=\"\u0420\u0438\u0441\u0443\u043d\u043e\u043a, \u0433\u0434\u0435 \u043e\u0434\u0438\u043d \u0441\u0442\u0438\u043a\u043c\u0435\u043d \u0433\u043e\u0432\u043e\u0440\u0438\u0442 \u0434\u0440\u0443\u0433\u043e\u043c\u0443 'hello I would like piece number\u2014', \u0430 \u0432\u0442\u043e\u0440\u043e\u0439 \u0434\u0443\u0448\u0438\u0442 \u0435\u0433\u043e \u0437\u0430 \u0448\u0435\u044e \u0438 \u0433\u043e\u0432\u043e\u0440\u0438\u0442 '00 00 00 01 00 (choke)'\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/54f\/bd6\/857\/54fbd685754d1b3c2af1f5ad15d51c09.png\"\/><\/p>\n<p>  <\/p>\n<h3 id=\"httpsblogjselipoststorrentinterpreting-messagesinterpretaciya-soobscheniy\"><a href=\"https:\/\/blog.jse.li\/posts\/torrent\/\/#interpreting-messages\">###<\/a>\u0418\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0446\u0438\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439<\/h3>\n<p>  <\/p>\n<p>\u0423 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0435\u0441\u0442\u044c \u0434\u043b\u0438\u043d\u0430, <strong>ID<\/strong> \u0438 <strong>\u043f\u043e\u043b\u0435\u0437\u043d\u0430\u044f \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0430 (payload)<\/strong>. \u042d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/b98\/cae\/547\/b98cae5474dfd4bd3bd4aa9f9daa512f.png\" alt=\"\u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0438\u043c\u0435\u0435\u0442 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u0434\u043b\u0438\u043d\u044b 4 \u0431\u0430\u0439\u0442\u0430, 1 \u0431\u0430\u0439\u0442 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 ID, \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u2014 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u043e\u043b\u0435\u0437\u043d\u0430\u044f \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0430\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/b98\/cae\/547\/b98cae5474dfd4bd3bd4aa9f9daa512f.png\"\/><\/p>\n<p>  <\/p>\n<p>\u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f \u0434\u043b\u0438\u043d\u044b. \u041e\u043d \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0431\u0430\u0439\u0442 \u0441\u043e\u0441\u0442\u0430\u0432\u0438\u0442 \u0434\u043b\u0438\u043d\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f. \u042d\u0442\u043e \u0446\u0435\u043b\u043e\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u0430\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u0432 32 \u0431\u0438\u0442\u0430, \u0442\u043e \u0435\u0441\u0442\u044c 4 \u0431\u0430\u0439\u0442\u0430 \u0432 \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0435 big-endian. \u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0431\u0430\u0439\u0442, <strong>ID<\/strong>, \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u0442, \u043a\u0430\u043a\u043e\u0439 \u0442\u0438\u043f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u2014 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0431\u0430\u0439\u0442 <code>2<\/code> \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u00abinterested\u00bb. \u041e\u0441\u0442\u0430\u0432\u0448\u0443\u044e\u0441\u044f \u0447\u0430\u0441\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 <strong>\u043f\u043e\u043b\u0435\u0437\u043d\u0430\u044f \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0430<\/strong>.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">type messageID uint8  const (     MsgChoke         messageID = 0     MsgUnchoke       messageID = 1     MsgInterested    messageID = 2     MsgNotInterested messageID = 3     MsgHave          messageID = 4     MsgBitfield      messageID = 5     MsgRequest       messageID = 6     MsgPiece         messageID = 7     MsgCancel        messageID = 8 )  \/\/ Message stores ID and payload of a message type Message struct {     ID      messageID     Payload []byte }  \/\/ Serialize serializes a message into a buffer of the form \/\/ &lt;length prefix>&lt;message ID>&lt;payload> \/\/ Interprets `nil` as a keep-alive message func (m *Message) Serialize() []byte {     if m == nil {         return make([]byte, 4)     }     length := uint32(len(m.Payload) + 1) \/\/ +1 for id     buf := make([]byte, 4+length)     binary.BigEndian.PutUint32(buf[0:4], length)     buf[4] = byte(m.ID)     copy(buf[5:], m.Payload)     return buf }<\/code><\/pre>\n<p>  <\/p>\n<p><a href=\"https:\/\/github.com\/veggiedefender\/torrent-client\/blob\/2bde944888e1195e81cc5d5b686f6ec3a9f08c25\/message\/message.go#L90-L103\">\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435<\/a><\/p>\n<p>  <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0438\u0437 \u043f\u043e\u0442\u043e\u043a\u0430 (stream), \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043b\u0435\u0434\u0443\u0435\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0443 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f. \u041c\u044b \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c 4 \u0431\u0430\u0439\u0442\u0430 \u0438 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u0443\u0435\u043c \u0438\u0445 \u043a\u0430\u043a <code>uint32<\/code>, \u0447\u0442\u043e\u0431\u044b \u0443\u0437\u043d\u0430\u0442\u044c <strong>\u0434\u043b\u0438\u043d\u0443<\/strong> \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f. \u0417\u0430\u0442\u0435\u043c \u0443\u0437\u043d\u0430\u0451\u043c \u0447\u0438\u0441\u043b\u043e \u0431\u0430\u0439\u0442, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c <strong>ID<\/strong> (\u043f\u0435\u0440\u0432\u044b\u0439 \u0431\u0430\u0439\u0442) \u0438 <strong>\u043f\u043e\u043b\u0435\u0437\u043d\u0443\u044e \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443<\/strong> \u2014 \u043e\u0441\u0442\u0430\u0432\u0448\u0438\u0435\u0441\u044f \u0431\u0430\u0439\u0442\u044b.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">\/\/ Read parses a message from a stream. Returns `nil` on keep-alive message func Read(r io.Reader) (*Message, error) {     lengthBuf := make([]byte, 4)     _, err := io.ReadFull(r, lengthBuf)     if err != nil {         return nil, err     }     length := binary.BigEndian.Uint32(lengthBuf)      \/\/ keep-alive message     if length == 0 {         return nil, nil     }      messageBuf := make([]byte, length)     _, err = io.ReadFull(r, messageBuf)     if err != nil {         return nil, err     }      m := Message{         ID:      messageID(messageBuf[0]),         Payload: messageBuf[1:],     }      return &amp;m, nil }<\/code><\/pre>\n<p>  <\/p>\n<p><a href=\"https:\/\/github.com\/veggiedefender\/torrent-client\/blob\/2bde944888e1195e81cc5d5b686f6ec3a9f08c25\/message\/message.go#L105-L131\">\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435<\/a><\/p>\n<p>  <\/p>\n<h3 id=\"bitovye-polya\">\u0411\u0438\u0442\u043e\u0432\u044b\u0435 \u043f\u043e\u043b\u044f<\/h3>\n<p>  <\/p>\n<p>\u041e\u0434\u0438\u043d \u0438\u0437 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0435\u0439\u0448\u0438\u0445 \u0442\u0438\u043f\u043e\u0432 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u2014 <strong>\u0431\u0438\u0442\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435 (bitfield)<\/strong>. \u042d\u0442\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u0430\u043d\u043d\u044b\u0445, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u0438\u0440\u044b \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u043a\u043e\u0434\u0438\u0440\u0443\u044e\u0442 \u0442\u0435 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c. \u0411\u0438\u0442\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435 \u043f\u043e\u0445\u043e\u0436\u0435 \u043d\u0430 \u0431\u0430\u0439\u0442\u043e\u0432\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 (byte array). \u0427\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u043a\u0430\u043a\u0438\u0435 \u0447\u0430\u0441\u0442\u0438 \u0443\u0436\u0435 \u0441\u043a\u0430\u0447\u0430\u043b\u0438\u0441\u044c, \u043d\u0443\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u044f <em>\u0431\u0438\u0442\u043e\u0432<\/em>, \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0440\u0430\u0432\u043d\u043e 1. \u041c\u043e\u0436\u0435\u0442\u0435 \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u044d\u0442\u043e \u0446\u0438\u0444\u0440\u043e\u0432\u044b\u043c \u044d\u043a\u0432\u0438\u0432\u0430\u043b\u0435\u043d\u0442\u043e\u043c \u043a\u0430\u0440\u0442\u044b \u043b\u043e\u044f\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043a\u0430\u043a\u043e\u0439-\u043d\u0438\u0431\u0443\u0434\u044c \u043a\u043e\u0444\u0435\u0439\u043d\u0438. \u0412\u043d\u0430\u0447\u0430\u043b\u0435 \u043a\u0430\u0440\u0442\u0430 \u043f\u0443\u0441\u0442\u0430, \u0438 \u0432\u0441\u0435 \u0431\u0438\u0442\u044b \u0440\u0430\u0432\u043d\u044b <code>0<\/code>. \u041c\u044b \u043c\u0435\u043d\u044f\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043d\u0430 <code>1<\/code>, \u0447\u0442\u043e\u0431\u044b \u00ab\u043f\u0440\u043e\u0448\u0442\u0430\u043c\u043f\u043e\u0432\u0430\u0442\u044c\u00bb \u0432\u0441\u0435 \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u043d\u0430 \u043a\u0430\u0440\u0442\u0435.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/8aa\/573\/e57\/8aa573e57a573cf44e259b223573b8f0.png\" alt=\"\u043a\u0430\u0440\u0442\u0430 \u043b\u043e\u044f\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043a\u043e\u0444\u0435\u0439\u043d\u0438 \u0441 \u043e\u0442\u043c\u0435\u0442\u043a\u0430\u043c\u0438 \u043d\u0430 4 \u043f\u0435\u0440\u0432\u044b\u0445 \u0438 \u043f\u0440\u0435\u0434\u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438, \u0447\u0442\u043e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0434\u0432\u043e\u0438\u0447\u043d\u043e\u043c\u0443 \u043a\u043e\u0434\u0443 11110010\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/8aa\/573\/e57\/8aa573e57a573cf44e259b223573b8f0.png\"\/><\/p>\n<p>  <\/p>\n<p>\u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u0431\u0438\u0442\u0430\u043c\u0438 \u0432\u043c\u0435\u0441\u0442\u043e \u0431\u0430\u0439\u0442\u043e\u0432, \u044d\u0442\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430\u043c\u043d\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u0435\u0435. \u041c\u044b \u043c\u043e\u0436\u0435\u043c \u0437\u0430\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e 8 \u0447\u0430\u0441\u0442\u044f\u0445 \u0432 \u043e\u0434\u043d\u043e\u043c \u0431\u0430\u0439\u0442\u0435 \u2014 \u044d\u0442\u043e \u0440\u0430\u0437\u043c\u0435\u0440 \u0442\u0438\u043f\u0430 <code>bool<\/code> [\u0443\u0442\u043e\u0447\u043d\u0438\u0442\u044c]. \u041d\u043e \u0446\u0435\u043d\u0430 \u0442\u0430\u043a\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u2014 \u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044c. \u0421\u0430\u043c\u044b\u0439 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0434\u043b\u044f \u0430\u0434\u0440\u0435\u0441\u0430\u0446\u0438\u0438 \u2014 \u0431\u0430\u0439\u0442. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0431\u0438\u0442\u0430\u043c\u0438 \u043d\u0443\u0436\u043d\u044b \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u0430\u043d\u0438\u043f\u0443\u043b\u044f\u0446\u0438\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">\/\/ A Bitfield represents the pieces that a peer has type Bitfield []byte  \/\/ HasPiece tells if a bitfield has a particular index set func (bf Bitfield) HasPiece(index int) bool {     byteIndex := index \/ 8     offset := index % 8     return bf[byteIndex]>>(7-offset)&amp;1 != 0 }  \/\/ SetPiece sets a bit in the bitfield func (bf Bitfield) SetPiece(index int) {     byteIndex := index \/ 8     offset := index % 8     bf[byteIndex] |= 1 &lt;&lt; (7 - offset) }<\/code><\/pre>\n<p>  <\/p>\n<p><a href=\"https:\/\/github.com\/veggiedefender\/torrent-client\/blob\/2bde944888e1195e81cc5d5b686f6ec3a9f08c25\/bitfield\/bitfield.go\">\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435<\/a><\/p>\n<p>  <\/p>\n<h2 id=\"sobiraem-vsyo-vmeste\">\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u0441\u0451 \u0432\u043c\u0435\u0441\u0442\u0435<\/h2>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0432\u0441\u0451, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0447\u0430\u0442\u044c \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b: \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u0438\u0440\u043e\u0432 \u0434\u043b\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u0430, \u0441\u0432\u044f\u0437\u044c \u0441 \u043d\u0438\u043c\u0438 \u043f\u043e TCP, \u0440\u0443\u043a\u043e\u043f\u043e\u0436\u0430\u0442\u0438\u0435, \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439. \u0412\u0430\u0436\u043d\u0435\u0439\u0448\u0438\u0435 \u0438\u0437 \u043e\u0441\u0442\u0430\u0432\u0448\u0438\u0445\u0441\u044f \u0437\u0430\u0434\u0430\u0447 \u2014 <strong>\u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u043d\u043e\u0441\u0442\u044c<\/strong> \u043f\u0440\u0438 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0441\u0432\u044f\u0437\u0438 \u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u043f\u0438\u0440\u0430\u043c\u0438 \u0438 <strong>\u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u043c \u043f\u0438\u0440\u043e\u0432<\/strong>, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u043c\u044b \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u043c. \u041e\u0431\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0435, \u043d\u043e \u0441\u043b\u043e\u0436\u043d\u044b\u0435.<\/p>\n<p>  <\/p>\n<h3 id=\"upravlenie-odnovremennoy-rabotoy-kanaly-v-kachestve-ocheredey\">\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u043e\u0439: \u043a\u0430\u043d\u0430\u043b\u044b \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0447\u0435\u0440\u0435\u0434\u0435\u0439<\/h3>\n<p>  <\/p>\n<p>\u0412 Go \u043f\u0430\u043c\u044f\u0442\u044c <a href=\"https:\/\/blog.golang.org\/share-memory-by-communicating\">\u043f\u0430\u043c\u044f\u0442\u044c \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043c\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u044e<\/a>. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043a\u0430\u043d\u0430\u043b Go \u043c\u043e\u0436\u043d\u043e \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043c\u0430\u043b\u043e\u0437\u0430\u0442\u0440\u0430\u0442\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a\u043e\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0439 \u043e\u0447\u0435\u0440\u0435\u0434\u044c\u044e.<\/p>\n<p>  <\/p>\n<p>\u041c\u044b \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u0434\u0432\u0430 \u043a\u0430\u043d\u0430\u043b\u0430 \u0434\u043b\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u043d\u044b\u0445 \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432: \u043e\u0434\u0438\u043d \u0434\u043b\u044f \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u0434\u0430\u0447 (\u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u0447\u0430\u0441\u0442\u0435\u0439) \u043c\u0435\u0436\u0434\u0443 \u043f\u0438\u0440\u0430\u043c\u0438, \u0430 \u0434\u0440\u0443\u0433\u043e\u0439 \u2014 \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0441\u043a\u0430\u0447\u0430\u043d\u043d\u044b\u0445 \u0447\u0430\u0441\u0442\u0435\u0439. \u041a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0435 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u044b \u043f\u043e\u043f\u0430\u0434\u0430\u044e\u0442 \u0432 \u043a\u0430\u043d\u0430\u043b \u0441 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430\u043c\u0438, \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u0431\u0443\u0444\u0435\u0440, \u0447\u0442\u043e\u0431\u044b \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043d\u0430\u0447\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u0443\u044e \u0441\u0431\u043e\u0440\u043a\u0443 \u0444\u0430\u0439\u043b\u0430.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">\/\/ Init queues for workers to retrieve work and send results workQueue := make(chan *pieceWork, len(t.PieceHashes)) results := make(chan *pieceResult) for index, hash := range t.PieceHashes {     length := t.calculatePieceSize(index)     workQueue &lt;- &amp;pieceWork{index, hash, length} }  \/\/ Start workers for _, peer := range t.Peers {     go t.startDownloadWorker(peer, workQueue, results) }  \/\/ Collect results into a buffer until full buf := make([]byte, t.Length) donePieces := 0 for donePieces &lt; len(t.PieceHashes) {     res := &lt;-results     begin, end := t.calculateBoundsForPiece(res.index)     copy(buf[begin:end], res.buf)     donePieces++ } close(workQueue)<\/code><\/pre>\n<p>  <\/p>\n<p><a href=\"https:\/\/github.com\/veggiedefender\/torrent-client\/blob\/2bde944888e1195e81cc5d5b686f6ec3a9f08c25\/p2p\/p2p.go#L188-L214\">\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435<\/a><\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u043e\u0432\u043e\u0434\u0438\u043c \u043f\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0443 \u0432 \u0433\u043e\u0440\u0443\u0442\u0438\u043d\u0435 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0433\u043e \u043d\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u0435 \u043f\u0438\u0440\u0430. \u041a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043d\u0438\u0445 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u0441\u044f \u043a \u043f\u0438\u0440\u0443, \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442 \u0440\u0443\u043a\u043e\u043f\u043e\u0436\u0430\u0442\u0438\u0435 \u0438 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0438 \u0438\u0437 <code>workQueue<\/code>, \u043f\u044b\u0442\u0430\u044f\u0441\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u0435, \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u043a\u0430\u0447\u0430\u043d\u043d\u044b\u0435 \u0447\u0430\u0441\u0442\u0438 \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u043f\u043e \u043a\u0430\u043d\u0430\u043b\u0443 <code>results<\/code>.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/85a\/81c\/3bb\/85a81c3bb18cbc0ab7d0c173b20f0666.png\" alt=\"\u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438 \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/85a\/81c\/3bb\/85a81c3bb18cbc0ab7d0c173b20f0666.png\"\/><\/p>\n<p>  <\/p>\n<pre><code class=\"go\">func (t *Torrent) startDownloadWorker(peer peers.Peer, workQueue chan *pieceWork, results chan *pieceResult) {     c, err := client.New(peer, t.PeerID, t.InfoHash)     if err != nil {         log.Printf(\"Could not handshake with %s. Disconnecting\\n\", peer.IP)         return     }     defer c.Conn.Close()     log.Printf(\"Completed handshake with %s\\n\", peer.IP)      c.SendUnchoke()     c.SendInterested()      for pw := range workQueue {         if !c.Bitfield.HasPiece(pw.index) {             workQueue &lt;- pw \/\/ Put piece back on the queue             continue         }          \/\/ Download the piece         buf, err := attemptDownloadPiece(c, pw)         if err != nil {             log.Println(\"Exiting\", err)             workQueue &lt;- pw \/\/ Put piece back on the queue             return         }          err = checkIntegrity(pw, buf)         if err != nil {             log.Printf(\"Piece #%d failed integrity check\\n\", pw.index)             workQueue &lt;- pw \/\/ Put piece back on the queue             continue         }          c.SendHave(pw.index)         results &lt;- &amp;pieceResult{pw.index, buf}     } }<\/code><\/pre>\n<p>  <\/p>\n<p><a href=\"https:\/\/github.com\/veggiedefender\/torrent-client\/blob\/2bde944888e1195e81cc5d5b686f6ec3a9f08c25\/p2p\/p2p.go#L133-L169\">\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435<\/a><\/p>\n<p>  <\/p>\n<h3 id=\"upravlenie-sostoyaniem-pirov\">\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u043c \u043f\u0438\u0440\u043e\u0432<\/h3>\n<p>  <\/p>\n<p>\u041c\u044b \u0431\u0443\u0434\u0435\u043c \u0441\u043b\u0435\u0434\u0438\u0442\u044c \u0437\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u043c \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u0438\u0440\u0430 \u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 (struct) \u0438 \u043c\u0435\u043d\u044f\u0442\u044c \u0435\u0433\u043e \u043f\u043e \u043c\u0435\u0440\u0435 \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439. \u0412 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0431\u0443\u0434\u0443\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u0442\u043e\u043c, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u044b \u0441\u043a\u0430\u0447\u0430\u043b\u0438 \u0443 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u0438\u0440\u0430, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u044b \u0443 \u043d\u0435\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0438\u043b\u0438 \u0438 \u00ab\u0437\u0430\u0433\u043b\u0443\u0448\u0435\u043d\u044b\u00bb \u043b\u0438 \u043c\u044b \u0438\u043c. \u0412\u0441\u0451 \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u043e \u0443\u0440\u043e\u0432\u043d\u044f \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0433\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0430, \u043d\u043e \u043f\u043e\u043a\u0430 \u043d\u0430\u043c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0441 \u043e\u0431\u044b\u0447\u043d\u044b\u043c \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0442\u0435\u043b\u0435\u043c.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">type pieceProgress struct {     index      int     client     *client.Client     buf        []byte     downloaded int     requested  int     backlog    int }  func (state *pieceProgress) readMessage() error {     msg, err := state.client.Read() \/\/ this call blocks     switch msg.ID {     case message.MsgUnchoke:         state.client.Choked = false     case message.MsgChoke:         state.client.Choked = true     case message.MsgHave:         index, err := message.ParseHave(msg)         state.client.Bitfield.SetPiece(index)     case message.MsgPiece:         n, err := message.ParsePiece(state.index, state.buf, msg)         state.downloaded += n         state.backlog--     }     return nil }<\/code><\/pre>\n<p>  <\/p>\n<p><a href=\"https:\/\/github.com\/veggiedefender\/torrent-client\/blob\/2bde944888e1195e81cc5d5b686f6ec3a9f08c25\/p2p\/p2p.go#L53-L83\">\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435<\/a><\/p>\n<p>  <\/p>\n<h3 id=\"pora-delat-zaprosy\">\u041f\u043e\u0440\u0430 \u0434\u0435\u043b\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b!<\/h3>\n<p>  <\/p>\n<p>\u0424\u0430\u0439\u043b\u0430\u043c\u0438, \u0447\u0430\u0441\u0442\u044f\u043c\u0438 \u0438 \u0445\u044d\u0448\u0430\u043c\u0438 \u0447\u0430\u0441\u0442\u0435\u0439 \u0434\u0435\u043b\u043e \u043d\u0435 \u043a\u043e\u043d\u0447\u0438\u0442\u0441\u044f. \u041c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u0439\u0442\u0438 \u0434\u0430\u043b\u044c\u0448\u0435 \u0438 \u0440\u0430\u0437\u0431\u0438\u0442\u044c \u0447\u0430\u0441\u0442\u0438 \u043d\u0430 <strong>\u0431\u043b\u043e\u043a\u0438<\/strong>. \u0411\u043b\u043e\u043a \u2014 \u044d\u0442\u043e \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u0447\u0430\u0441\u0442\u0438. \u0415\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043f\u043e <strong>\u0438\u043d\u0434\u0435\u043a\u0441\u0443 \u0447\u0430\u0441\u0442\u0438<\/strong>, \u0432 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043e\u043d \u0432\u0445\u043e\u0434\u0438\u0442, <strong>\u0431\u0430\u0439\u0442\u043e\u0432\u043e\u043c\u0443 \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u044e<\/strong> \u0432\u043d\u0443\u0442\u0440\u0438 \u0447\u0430\u0441\u0442\u0438 \u0438 <strong>\u0434\u043b\u0438\u043d\u0435<\/strong>. \u0423 \u043f\u0438\u0440\u043e\u0432 \u043e\u0431\u044b\u0447\u043d\u043e \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u044e\u0442\u0441\u044f <em>\u0431\u043b\u043e\u043a\u0438<\/em>. \u0420\u0430\u0437\u043c\u0435\u0440 \u0431\u043b\u043e\u043a\u0430, \u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e, 16 \u041a\u0411, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0447\u0430\u0441\u0442\u0438 \u0432 256 KB \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f 16 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<\/p>\n<p>  <\/p>\n<p>\u041f\u0438\u0440 \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0430\u0437\u0440\u044b\u0432\u0430\u0442\u044c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0430 \u0431\u043b\u043e\u043a \u0431\u043e\u043b\u0435\u0435 16 \u041a\u0411. \u041d\u043e, \u043a\u0430\u043a \u044f \u0437\u043d\u0430\u044e \u043f\u043e \u0441\u0432\u043e\u0435\u043c\u0443 \u043e\u043f\u044b\u0442\u0443, \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043d\u0430 \u0431\u043b\u043e\u043a\u0438 \u0434\u043e 128 \u041a\u0411. \u041d\u043e \u0443 \u043c\u0435\u043d\u044f \u043f\u0440\u0438\u0440\u043e\u0441\u0442 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0431\u044b\u043b \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0441\u043a\u0440\u043e\u043c\u043d\u044b\u043c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043b\u0443\u0447\u0448\u0435, \u043f\u0440\u0438\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0439 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438.<\/p>\n<p>  <\/p>\n<h3 id=\"konveyernaya-obrabotka\">\u041a\u043e\u043d\u0432\u0435\u0439\u0435\u0440\u043d\u0430\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430<\/h3>\n<p>  <\/p>\n<p>\u0414\u0432\u0443\u0441\u0442\u043e\u0440\u043e\u043d\u043d\u044f\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u043f\u043e \u0441\u0435\u0442\u0438 (network round-trips) \u043e\u0431\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0434\u043e\u0440\u043e\u0433\u043e, \u0430 \u043f\u043e\u0431\u043b\u043e\u0447\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0437\u0430\u0447\u0430\u0441\u0442\u0443\u044e \u043f\u0440\u043e\u0441\u0442\u043e \u0443\u0431\u0438\u0439\u0441\u0442\u0432\u0435\u043d\u043d\u044b \u0434\u043b\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u0430\u0436\u043d\u0430 <strong>\u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440\u043d\u0430\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430<\/strong> \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u043f\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0431\u0440\u0435\u043c\u044f \u043d\u0435\u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d\u043d\u044b\u0445 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0433\u043e \u0447\u0438\u0441\u043b\u0430 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u044b\u043c. \u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043d\u0430 \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u043f\u043e\u0432\u044b\u0441\u0438\u0442\u044c \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u043d\u0443\u044e \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c \u043d\u0430\u0448\u0435\u0433\u043e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/97e\/76f\/24d\/97e76f24d5e50fbf8f60559483a0d6b2.png\" alt=\"\u0414\u0432\u0435 \u0432\u0435\u0442\u043a\u0438 email \u0441 \u0441\u0438\u043c\u0443\u043b\u044f\u0446\u0438\u0435\u0439 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043f\u0438\u0440\u043e\u0432. \u0412\u0435\u0442\u043a\u0430 \u0441\u043b\u0435\u0432\u0430 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u0440\u0438\u0436\u0434\u044b \u0434\u0430\u043d \u043e\u0442\u0432\u0435\u0442. \u0412 \u0432\u0435\u0442\u043a\u0435 \u0441\u043f\u0440\u0430\u0432\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u044b \u0442\u0440\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u0438 \u043d\u0430 \u043d\u0438\u0445 \u0431\u044b\u0441\u0442\u0440\u043e \u0434\u0430\u043d\u043e \u0442\u0440\u0438 \u043e\u0442\u0432\u0435\u0442\u0430\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/97e\/76f\/24d\/97e76f24d5e50fbf8f60559483a0d6b2.png\"\/><\/p>\n<p>  <\/p>\n<p>\u041a\u043b\u0438\u0435\u043d\u0442\u044b BitTorrent \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u043e\u043d\u043d\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0438\u0437 5 \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440\u043d\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 (pipelined requests), \u0438 \u044f \u0432\u043e\u0437\u044c\u043c\u0443 \u0442\u043e \u0436\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435. \u041a\u0430\u043a \u044f \u0443\u0432\u0438\u0434\u0435\u043b, \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u0435 \u044d\u0442\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0443\u0434\u0432\u043e\u0438\u0442\u044c \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f. \u0411\u043e\u043b\u0435\u0435 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 <a href=\"https:\/\/luminarys.com\/posts\/writing-a-bittorrent-client.html\">\u0430\u0434\u0430\u043f\u0442\u0438\u0432\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 (adaptive queue size)<\/a>, \u0447\u0442\u043e \u043b\u0443\u0447\u0448\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044f\u043c \u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u043c \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0441\u0435\u0442\u0435\u0439. \u0421 \u044d\u0442\u0438\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e, \u0441\u0442\u043e\u0438\u0442 \u043f\u043e\u0438\u0433\u0440\u0430\u0442\u044c. \u042d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0438 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">\/\/ MaxBlockSize is the largest number of bytes a request can ask for const MaxBlockSize = 16384  \/\/ MaxBacklog is the number of unfulfilled requests a client can have in its pipeline const MaxBacklog = 5  func attemptDownloadPiece(c *client.Client, pw *pieceWork) ([]byte, error) {     state := pieceProgress{         index:  pw.index,         client: c,         buf:    make([]byte, pw.length),     }      \/\/ Setting a deadline helps get unresponsive peers unstuck.     \/\/ 30 seconds is more than enough time to download a 262 KB piece     c.Conn.SetDeadline(time.Now().Add(30 * time.Second))     defer c.Conn.SetDeadline(time.Time{}) \/\/ Disable the deadline      for state.downloaded &lt; pw.length {         \/\/ If unchoked, send requests until we have enough unfulfilled requests         if !state.client.Choked {             for state.backlog &lt; MaxBacklog &amp;&amp; state.requested &lt; pw.length {                 blockSize := MaxBlockSize                 \/\/ Last block might be shorter than the typical block                 if pw.length-state.requested &lt; blockSize {                     blockSize = pw.length - state.requested                 }                  err := c.SendRequest(pw.index, state.requested, blockSize)                 if err != nil {                     return nil, err                 }                 state.backlog++                 state.requested += blockSize             }         }          err := state.readMessage()         if err != nil {             return nil, err         }     }      return state.buf, nil }<\/code><\/pre>\n<p>  <\/p>\n<p><a href=\"https:\/\/github.com\/veggiedefender\/torrent-client\/blob\/2bde944888e1195e81cc5d5b686f6ec3a9f08c25\/p2p\/p2p.go#L85-L123\">\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435<\/a><\/p>\n<p>  <\/p>\n<h3 id=\"httpsblogjselipoststorrentmaingomaingo\"><a href=\"https:\/\/blog.jse.li\/posts\/torrent\/\/#maingo\">###<\/a>main.go<\/h3>\n<p>  <\/p>\n<p>\u042d\u0442\u043e \u043d\u0435 \u0437\u0430\u0439\u043c\u0451\u0442 \u043c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438. \u041c\u044b \u043f\u043e\u0447\u0442\u0438 \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b\u0438.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">package main  import (     \"log\"     \"os\"      \"github.com\/veggiedefender\/torrent-client\/torrentfile\" )  func main() {     inPath := os.Args[1]     outPath := os.Args[2]      tf, err := torrentfile.Open(inPath)     if err != nil {         log.Fatal(err)     }      err = tf.DownloadToFile(outPath)     if err != nil {         log.Fatal(err)     } }<\/code><\/pre>\n<p>  <\/p>\n<p><a href=\"https:\/\/github.com\/veggiedefender\/torrent-client\/blob\/2bde944888e1195e81cc5d5b686f6ec3a9f08c25\/main.go\">\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435<\/a><\/p>\n<h1 id=\"eto-ne-vsyo\">\u042d\u0442\u043e \u043d\u0435 \u0432\u0441\u0451<\/h1>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u043a\u0440\u0430\u0442\u043a\u043e\u0441\u0442\u0438 \u044f \u0432\u043a\u043b\u044e\u0447\u0438\u043b \u0441\u044e\u0434\u0430 \u043b\u0438\u0448\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043e\u0432 \u043a\u043e\u0434\u0430. \u0417\u0430\u043c\u0435\u0447\u0443, \u0447\u0442\u043e \u0432\u0435\u0441\u044c \u0441\u0432\u044f\u0437\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434 (glue code), \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0430\u043d\u0430\u043b\u0438\u0437 (parsing), \u044e\u043d\u0438\u0442-\u0442\u0435\u0441\u0442\u044b \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0441\u043a\u0443\u0447\u043d\u044b\u0435 \u0441\u0442\u0440\u043e\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u044f \u043e\u043f\u0443\u0441\u0442\u0438\u043b. <a href=\"https:\/\/github.com\/veggiedefender\/torrent-client\">\u041f\u043e\u043b\u043d\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e<\/a> \u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u043d\u0430 Github.<\/p>\n<p>  <\/p>\n<p><a href=\"https:\/\/skillfactory.ru\/catalogue?utm_source=habr&amp;utm_medium=habr&amp;utm_campaign=article&amp;utm_content=sf_allcourses_310122&amp;utm_term=conc\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/cq\/na\/88\/cqna880todtt287i6ffb12uzzwk.png\" data-src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/cq\/na\/88\/cqna880todtt287i6ffb12uzzwk.png\"\/><\/a><\/p>\n<p>  <\/p>\n<ul>\n<li><u><a href=\"https:\/\/skillfactory.ru\/data-scientist-pro?utm_source=habr&amp;utm_medium=habr&amp;utm_campaign=article&amp;utm_content=data-science_dspr_310122&amp;utm_term=conc\">\u041f\u0440\u043e\u0444\u0435\u0441\u0441\u0438\u044f Data Scientist (24 \u043c\u0435\u0441\u044f\u0446\u0430)<\/a><\/u><\/li>\n<li><u><a href=\"https:\/\/skillfactory.ru\/python-fullstack-web-developer?utm_source=habr&amp;utm_medium=habr&amp;utm_campaign=article&amp;utm_content=coding_fpw_310122&amp;utm_term=conc\">\u041f\u0440\u043e\u0444\u0435\u0441\u0441\u0438\u044f Fullstack-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043d\u0430\u00a0Python (16 \u043c\u0435\u0441\u044f\u0446\u0435\u0432)<\/a><\/u><\/li>\n<\/ul>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041a\u0440\u0430\u0442\u043a\u0438\u0439 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \u043a\u0443\u0440\u0441\u043e\u0432<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<p><strong>Data Science \u0438\u00a0Machine Learning<\/strong><\/p>\n<p>  <\/p>\n<ul>\n<li><a href=\"https:\/\/skillfactory.ru\/data-scientist-pro?utm_source=habr&amp;utm_medium=habr&amp;utm_campaign=article&amp;utm_content=data-science_dspr_310122&amp;utm_term=cat\">\u041f\u0440\u043e\u0444\u0435\u0441\u0441\u0438\u044f Data Scientist<\/a><\/li>\n<li><a href=\"https:\/\/skillfactory.ru\/data-analyst-pro?utm_source=habr&amp;utm_medium=habr&amp;utm_campaign=article&amp;utm_content=analytics_dapr_310122&amp;utm_term=cat\">\u041f\u0440\u043e\u0444\u0435\u0441\u0441\u0438\u044f Data Analyst<\/a><\/li>\n<li><a href=\"https:\/\/skillfactory.ru\/matematika-dlya-data-science#syllabus?utm_source=habr&amp;utm_medium=habr&amp;utm_campaign=article&amp;utm_content=data-science_mat_310122&amp;utm_term=cat\">\u041a\u0443\u0440\u0441 \u00ab\u041c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0430 \u0434\u043b\u044f Data Science\u00bb<\/a><\/li>\n<li><a href=\"https:\/\/skillfactory.ru\/matematika-i-machine-learning-dlya-data-science?utm_source=habr&amp;utm_medium=habr&amp;utm_campaign=article&amp;utm_content=data-science_matml_310122&amp;utm_term=cat\">\u041a\u0443\u0440\u0441 \u00ab\u041c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0430 \u0438\u00a0Machine Learning \u0434\u043b\u044f Data Science\u00bb<\/a><\/li>\n<li><a href=\"https:\/\/skillfactory.ru\/data-engineer?utm_source=habr&amp;utm_medium=habr&amp;utm_campaign=article&amp;utm_content=data-science_dea_310122&amp;utm_term=cat\">\u041a\u0443\u0440\u0441 \u043f\u043e\u00a0Data Engineering<\/a><\/li>\n<li><a href=\"https:\/\/skillfactory.ru\/machine-learning-i-deep-learning?utm_source=habr&amp;utm_medium=habr&amp;utm_campaign=article&amp;utm_content=data-science_mldl_310122&amp;utm_term=cat\">\u041a\u0443\u0440\u0441 \u00abMachine Learning \u0438\u00a0Deep Learning\u00bb<\/a><\/li>\n<li><a href=\"https:\/\/skillfactory.ru\/machine-learning?utm_source=habr&amp;utm_medium=habr&amp;utm_campaign=article&amp;utm_content=data-science_ml_310122&amp;utm_term=cat\">\u041a\u0443\u0440\u0441 \u043f\u043e\u00a0Machine Learning<\/a><\/li>\n<\/ul>\n<p>  <\/p>\n<p><strong>Python, \u0432\u0435\u0431-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430<\/strong><\/p>\n<p>  <\/p>\n<ul>\n<li><a href=\"https:\/\/skillfactory.ru\/python-fullstack-web-developer?utm_source=habr&amp;utm_medium=habr&amp;utm_campaign=article&amp;utm_content=coding_fpw_310122&amp;utm_term=cat\">\u041f\u0440\u043e\u0444\u0435\u0441\u0441\u0438\u044f Fullstack-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043d\u0430\u00a0Python<\/a><\/li>\n<li><a href=\"https:\/\/skillfactory.ru\/python-for-web-developers?utm_source=habr&amp;utm_medium=habr&amp;utm_campaign=article&amp;utm_content=coding_pws_310122&amp;utm_term=cat\">\u041a\u0443\u0440\u0441 \u00abPython \u0434\u043b\u044f \u0432\u0435\u0431-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438\u00bb<\/a><\/li>\n<li><a href=\"https:\/\/skillfactory.ru\/frontend-razrabotchik?utm_source=habr&amp;utm_medium=habr&amp;utm_campaign=article&amp;utm_content=coding_fr_310122&amp;utm_term=cat\">\u041f\u0440\u043e\u0444\u0435\u0441\u0441\u0438\u044f Frontend-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a<\/a><\/li>\n<li><a href=\"https:\/\/skillfactory.ru\/webdev?utm_source=habr&amp;utm_medium=habr&amp;utm_campaign=article&amp;utm_content=coding_webdev_310122&amp;utm_term=cat\">\u041f\u0440\u043e\u0444\u0435\u0441\u0441\u0438\u044f \u0412\u0435\u0431-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a<\/a><\/li>\n<\/ul>\n<p>  <\/p>\n<p><strong>\u041c\u043e\u0431\u0438\u043b\u044c\u043d\u0430\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430<\/strong><\/p>\n<p>  <\/p>\n<ul>\n<li><a href=\"https:\/\/skillfactory.ru\/ios-razrabotchik-s-nulya?utm_source=habr&amp;utm_medium=habr&amp;utm_campaign=article&amp;utm_content=coding_ios_310122&amp;utm_term=cat\">\u041f\u0440\u043e\u0444\u0435\u0441\u0441\u0438\u044f iOS-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a<\/a><\/li>\n<li><a href=\"https:\/\/skillfactory.ru\/android-razrabotchik?utm_source=habr&amp;utm_medium=habr&amp;utm_campaign=article&amp;utm_content=coding_andr_310122&amp;utm_term=cat\">\u041f\u0440\u043e\u0444\u0435\u0441\u0441\u0438\u044f Android-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a<\/a><\/li>\n<\/ul>\n<p>  <\/p>\n<p><strong>Java \u0438\u00a0C#<\/strong><\/p>\n<p>  <\/p>\n<ul>\n<li><a href=\"https:\/\/skillfactory.ru\/java-razrabotchik?utm_source=habr&amp;utm_medium=habr&amp;utm_campaign=article&amp;utm_content=coding_java_310122&amp;utm_term=cat\">\u041f\u0440\u043e\u0444\u0435\u0441\u0441\u0438\u044f Java-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a<\/a><\/li>\n<li><a href=\"https:\/\/skillfactory.ru\/java-qa-engineer-testirovshik-po?utm_source=habr&amp;utm_medium=habr&amp;utm_campaign=article&amp;utm_content=coding_qaja_310122&amp;utm_term=cat\">\u041f\u0440\u043e\u0444\u0435\u0441\u0441\u0438\u044f QA-\u0438\u043d\u0436\u0435\u043d\u0435\u0440 \u043d\u0430\u00a0JAVA<\/a><\/li>\n<li><a href=\"https:\/\/skillfactory.ru\/c-sharp-razrabotchik?utm_source=habr&amp;utm_medium=habr&amp;utm_campaign=article&amp;utm_content=coding_cdev_310122&amp;utm_term=cat\">\u041f\u0440\u043e\u0444\u0435\u0441\u0441\u0438\u044f C#-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a<\/a><\/li>\n<li><a href=\"https:\/\/skillfactory.ru\/game-razrabotchik-na-unity-i-c-sharp?utm_source=habr&amp;utm_medium=habr&amp;utm_campaign=article&amp;utm_content=coding_gamedev_310122&amp;utm_term=cat\">\u041f\u0440\u043e\u0444\u0435\u0441\u0441\u0438\u044f \u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0438\u0433\u0440 \u043d\u0430\u00a0Unity<\/a><\/li>\n<\/ul>\n<p>  <\/p>\n<p><strong>\u041e\u0442\u00a0\u043e\u0441\u043d\u043e\u0432\u00a0\u2014 \u0432\u00a0\u0433\u043b\u0443\u0431\u0438\u043d\u0443<\/strong><\/p>\n<p>  <\/p>\n<ul>\n<li><a href=\"https:\/\/skillfactory.ru\/algoritmy-i-struktury-dannyh?utm_source=habr&amp;utm_medium=habr&amp;utm_campaign=article&amp;utm_content=coding_algo_310122&amp;utm_term=cat\">\u041a\u0443\u0440\u0441 \u00ab\u0410\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b \u0438\u00a0\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0434\u0430\u043d\u043d\u044b\u0445\u00bb<\/a><\/li>\n<li><a href=\"https:\/\/skillfactory.ru\/c-plus-plus-razrabotchik?utm_source=habr&amp;utm_medium=habr&amp;utm_campaign=article&amp;utm_content=coding_cplus_310122&amp;utm_term=cat\">\u041f\u0440\u043e\u0444\u0435\u0441\u0441\u0438\u044f C++ \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a<\/a><\/li>\n<li><a href=\"https:\/\/skillfactory.ru\/cyber-security-etichnij-haker?utm_source=habr&amp;utm_medium=habr&amp;utm_campaign=article&amp;utm_content=coding_hacker_310122&amp;utm_term=cat\">\u041f\u0440\u043e\u0444\u0435\u0441\u0441\u0438\u044f \u00ab\u0411\u0435\u043b\u044b\u0439 \u0445\u0430\u043a\u0435\u0440\u00bb<\/a><\/li>\n<\/ul>\n<p>  <\/p>\n<p><strong>\u0410\u00a0\u0442\u0430\u043a\u0436\u0435<\/strong><\/p>\n<p>  <\/p>\n<ul>\n<li><a href=\"https:\/\/skillfactory.ru\/devops-engineer?utm_source=habr&amp;utm_medium=habr&amp;utm_campaign=article&amp;utm_content=coding_devops_310122&amp;utm_term=cat\">\u041a\u0443\u0440\u0441 \u043f\u043e\u00a0DevOps<\/a><\/li>\n<li><a href=\"https:\/\/skillfactory.ru\/catalogue?utm_source=habr&amp;utm_medium=habr&amp;utm_campaign=article&amp;utm_content=sf_allcourses_310122&amp;utm_term=cat\">\u0412\u0441\u0435 \u043a\u0443\u0440\u0441\u044b<\/a><\/li>\n<\/ul>\n<\/div><\/div>\n<\/div>\n<\/div>\n<\/div>\n<p> <!----> <!----><\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/company\/skillfactory\/blog\/714044\/\"> https:\/\/habr.com\/ru\/company\/skillfactory\/blog\/714044\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/43d\/908\/e6f\/43d908e6f14b60294b8bb69b5e8ad600.png\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/43d\/908\/e6f\/43d908e6f14b60294b8bb69b5e8ad600.png\"\/><\/p>\n<p>  <\/p>\n<p>BitTorrent \u2014 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u043e\u0432 \u0447\u0435\u0440\u0435\u0437 \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442. \u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0439 \u043a\u043b\u0438\u0435\u043d\u0442\/\u0441\u0435\u0440\u0432\u0435\u0440, \u043a\u043e\u0433\u0434\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043a\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u044e\u0442\u0441\u044f \u043a \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u0443 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0444\u0438\u043b\u044c\u043c\u0430 \u043d\u0430 Netflix \u0438\u043b\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0432\u0435\u0431-\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b), \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u0438 \u0441\u0435\u0442\u0438 BitTorrent, \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0435 <strong>\u043e\u0434\u043d\u043e\u0440\u0430\u043d\u0433\u043e\u0432\u044b\u043c\u0438 \u0443\u0437\u043b\u0430\u043c\u0438<\/strong>, \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u044e\u0442 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u044b \u0444\u0430\u0439\u043b\u043e\u0432 \u0434\u0440\u0443\u0433 \u0441 \u0434\u0440\u0443\u0433\u0430. \u042d\u0442\u043e \u0442\u043e, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 BitTorrent <strong>\u043e\u0434\u043d\u043e\u0440\u0430\u043d\u0433\u043e\u0432\u044b\u043c<\/strong> \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u043e\u043c. \u0418\u0441\u0441\u043b\u0435\u0434\u0443\u0435\u043c, \u043a\u0430\u043a \u043e\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u0438 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c \u043e\u0434\u043d\u043e\u0440\u0430\u043d\u0433\u043e\u0432\u044b\u0435 \u0443\u0437\u043b\u044b \u0438 \u043e\u0431\u043c\u0435\u043d\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0441 \u043d\u0438\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-344800","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/344800","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=344800"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/344800\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=344800"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=344800"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=344800"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}