BitTorrent:下载不启动
我正在尝试在Laravel中实现一个bittorrent跟踪器 。 但是,由于下载无法启动,所以暂时停滞不前。 有一个似乎是播种的同伴,我100%确定它是可以连接的。 但是,当我在另一台机器上运行第二个客户端时,下载将无法启动。 它被卡在“连接到同行”(uTorrent)。
当客户发布消息时,我会发送以下回复:
d8:intervali1000e12:min intervali300e5:peers18: ؤ i ؑ XÚJU 6e
在下载客户端中,我有以下数据:
这是我的通知代码:
<?php namespace App\Http\Controllers\Announce; use App\Helpers\BencodeHelper; use App\Models\Peer; use App\Models\PeerTorrent; use App\Models\Torrent; use App\Models\User; use Illuminate\Http\Request; use Illuminate\Http\Response; use Illuminate\Routing\Controller; use Illuminate\Support\Facades\Input; use Illuminate\Support\Facades\Log; class AnnounceController extends Controller { const __INTERVAL = 1000; const __TIMEOUT = 120; const __INTERVAL_MIN = 60; const __MAX_PPR = 20; public function announce(Request $request) { Log::info($request->fullUrl()); $status = 200; $content = ""; $passkey = Input::get('passkey'); $peer_id = Input::get('peer_id'); $port = Input::get('port'); $info_hash = Input::get('info_hash'); $downloaded = Input::get('uploaded') ? intval(Input::get('uploaded')) : 0; $uploaded = Input::get('uploaded') ? intval(Input::get('uploaded')) : 0; $left = Input::get('left') ? intval(Input::get('left')) : 0; $compact = Input::get('compact') ? intval(Input::get('compact')) : 0; $no_peer_id = Input::get('no_peer_id') ? intval(Input::get('no_peer_id')) : 0; $ipAddress = ''; // Check for X-Forwarded-For headers and use those if found if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && ('' !== trim($_SERVER['HTTP_X_FORWARDED_FOR']))) { $ipAddress = (trim($_SERVER['HTTP_X_FORWARDED_FOR'])); } else { if (isset($_SERVER['REMOTE_ADDR']) && ('' !== trim($_SERVER['REMOTE_ADDR']))) { $ipAddress = (trim($_SERVER['REMOTE_ADDR'])); } } $port = $_SERVER['REMOTE_PORT']; /*if(!$port || !ctype_digit($port) || intval($port) < 1 || intval($port) > 65535) { $content = BencodeHelper::track("Invalid client port."); $status = 401; return (new Response(AnnounceController::track($content), $status)) ->header('Content-Type', $value); } if ($port == 999 && substr($peer_id, 0, 10) == '-TO0001-XX') { die("d8:completei0e10:incompletei0e8:intervali600e12:min intervali60e5:peersld2:ip12:72.14.194.184:port3:999ed2:ip11:72.14.194.14:port3:999ed2:ip12:72.14.194.654:port3:999eee"); }*/ if (!$passkey) { $content = BencodeHelper::track("Missing passkey."); $status = 401; return (new Response(AnnounceController::track($content), $status)) ->header('Content-Type', $value); } $torrent = Torrent::getByInfoHash(sha1($info_hash)); if (!$torrent || $torrent == null) { $content = "Torrent not registered with this tracker."; $status = 404; return (new Response(AnnounceController::track($content), $status)) ->header('Content-Type', $value); } $user = User::has('passkeys', '=', $passkey)->get(); if ($user == null) { $content = BencodeHelper::track("Invalid passkey."); $status = 401; return (new Response(AnnounceController::track($content), $status)) ->header('Content-Type', $value); } $peer = Peer::getByHashAndPasskey(bin2hex($peer_id), $passkey); if ($peer == null) { $peer = Peer::create([ 'hash' => bin2hex($peer_id), 'user_agent' => $_SERVER['HTTP_USER_AGENT'], 'ip_address' => $ipAddress, 'passkey' => $passkey, 'port' => $port ]); } if (!$info_hash || strlen($info_hash) != 20) { $content = BencodeHelper::track("Invalid info_hash."); $status = 401; return (new Response(AnnounceController::track($content), $status)) ->header('Content-Type', $value); } $peer_torrent = PeerTorrent::getByPeerAndTorrent($peer, $torrent); if ($peer_torrent == null) { $peer_torrent = PeerTorrent::create([ 'peer_id' => $peer->id, 'torrent_id' => $torrent->id, 'uploaded' => $uploaded, 'downloaded' => $downloaded, 'left' => $left, 'stopped' => false ]); } else { $peer_torrent->uploaded = $uploaded; $peer_torrent->downloaded = $downloaded; $peer_torrent->left = $left; $peer_torrent->save(); } $seeders = $torrent->getSeedersCount(); $leechers = $torrent->getLeechersCount(); $resp = ""; if ($compact != 1) { $resp = "d" . $this->benc_str("interval") . "i" . AnnounceController::__INTERVAL . "e" . $this->benc_str("peers") . "l"; } else { $resp = "d" . $this->benc_str("interval") . "i" . AnnounceController::__INTERVAL . "e" . $this->benc_str("min interval") . "i" . 300 . "e5:" . "peers"; } $peer = array(); $peer_num = 0; foreach ($torrent->getPeersArray() as $row) { if ($compact != 1) { if ($row["peer_id"] === $peer->hash) { continue; } $resp .= "d" . $this->benc_str("ip") . $this->benc_str($row['ip']); if ($no_peer_id == 0) { $resp .= $this->benc_str("peer id") . $this->benc_str($row["peer_id"]); } $resp .= $this->benc_str("port") . "i" . $row["port"] . "e" . "e"; } else { $peer_ip = explode('.', $row["ip"]); $peer_ip = pack("C*", $peer_ip[0], $peer_ip[1], $peer_ip[2], $peer_ip[3]); $peer_port = pack("n*", (int)$row["port"]); $time = intval((time() % 7680) / 60); if ($left == 0) { $time += 128; } $time = pack("C", $time); $peer[] = $time . $peer_ip . $peer_port; $peer_num++; } } if ($compact != 1) { $resp .= "ee"; } else { $o = ""; for ($i = 0; $i < $peer_num; $i++) { $o .= substr($peer[$i], 1, 6); } $resp .= strlen($o) . ':' . $o . 'e'; } $this->benc_resp_raw($resp); } public function benc_resp($d) { return $this->benc_resp_raw($this->benc(array('type' => 'dictionary', 'value' => $d))); } public function benc_resp_raw($x) { header("Content-Type: text/plain"); header("Pragma: no-cache"); if ($_SERVER['HTTP_ACCEPT_ENCODING'] == 'gzip') { header("Content-Encoding: gzip"); echo gzencode($x, 9, FORCE_GZIP); } else { echo $x; } } function benc($obj) { if (!is_array($obj) || !isset($obj["type"]) || !isset($obj["value"])) return; $c = $obj["value"]; switch ($obj["type"]) { case "string": return $this->benc_str($c); case "integer": return $this->benc_int($c); case "list": return $this->benc_list($c); case "dictionary": return $this->benc_dict($c); default: return; } } public function benc_str($s) { return strlen($s) . ":$s"; } public function benc_int($i) { return "i" . $i . "e"; } public function benc_list($a) { $s = "l"; foreach ($a as $e) { $s .= $this->benc($e); } $s .= "e"; return $s; } public function benc_dict($d) { $s = "d"; $keys = array_keys($d); sort($keys); foreach ($keys as $k) { $v = $d[$k]; $s .= $this->benc_str($k); $s .= $this->benc($v); } $s .= "e"; return $s; } public function hex2bin($hex) { $r = ''; for ($i = 0; $i < strlen($hex); $i += 2) { $r .= chr(hexdec($hex{$i} . $hex{($i + 1)})); } return $r; } }
我不太清楚我在这里错过了什么。
也许是因为你不断设置
->header('Content-Type', $value);
没有设置$value
? 那么“宣布 – 回应”是畸形的?