문서 편집

토렌트 (Torrent)

비트토렌트파일 공유

torrent p2p 토렌트 유토렌트 utorrent

106 참조

개념

  • Tracker 일종의 서버로 swarm 안에 seeder와 peer를 모니터링한다. 클라이언트tracker 서버로 자기 정보를 보내고 현재 swarm 안의 seeder와 peer에 관한 정보를 받는다. Tracker 서버는 데이터 전송에 직접적인 영향이나 관계는 없으며 공유되는 파일의 복사본을 가지고 있지 않는다. 현재 비트토렌트 버전은 tracker 서버 없이도 구현이 가능하도록 되어 있다. 그러나 대부분의 비트토렌트는 현재까지는 tracker 서버를 많이 사용하고 있다.
  • seed 토렌트 프로토콜을 이용해 파일을 이미 모두 내려받은 클라이언트.
  • peer 토렌트 프로토콜을 이용해 파일을 내려받고 있는 클라이언트. 자신이 받은 내용은 곧 다시 배포하게 되므로 업로더/다운로더와 같은 개념은 아니다.

마그넷 (Magnet)도 참조.

토렌트 검색 사이트들

국내

이름 참고
토다 망함..
토렌트모아 TV,AV 위주… 가입불필요, AV는 필요
투쉐어 망함
투공유 방심위가 차단함
토르 한글검색엔진.. 단순 검색이라 가짜가 많음.

국내 토렌트 사이트 보기 : 한글 토렌트(torrent) 검색기 "티토렌트(Ttorrent)"

국외

이름 참고
빗스눕 망함
Torrentz 망함
http://movietorrents.eu 망함
mininova 망함
제뷔정키스일본 av전문. 한국 ip 차단, 프록시 필요
SCRAPEtorrent 접속불가.
bittorrent 토렌트 사이트가 아니라 클라이언트 다운로드 사이트로 바뀌었음.
thepiratebay
torrentportal
btmon
sumotorrent
torrentreactor
btjunkie
extratorrent
tokyo-tosho 애니메이션
nyaatorrents 애니메이션
hongfire 애니메이션
akiba online 애니메이션 차단

공개 트래커

업로드

bitsnoop 사이트는 토렌트 검색엔진으로서 자체에 torrent 파일을 저장하지 않는다. 따라서 다른 곳에 업로드를 하면 그것을 봇이 검색을 해서 자동으로 올라가는 방식이다. 아래의 곳에 올리면 자동적으로 검색을 해서 올라간다. 토렌트 파일을 머땅히 업로드할 곳이 없을때 좋은 방법이기도 하다.

Disable DHT When Using Private Trackers

회원제로 관리되어 로그인 후 사용하는 사이트에서 토렌트를 받을 때에는 항상 DHT를 Disable로 설정해야 한다. DHT가 Enable일 때에는 인증되지 않은 사용자가 다운을 받을 수도 있다. 따라서..

  • 엉뚱한 사람에게 업로드를 하게 된다.
  • 업로드 트래픽을 사이트에서 인정 받을 수 없게된다.
  • 그러면 점수가 안올라간다.

가십

Mininova 패소..

Pirate bay 폐쇄

demonioid 폐쇄...

쩝.

국내 토렌트 공유 사이트 단속

http://media.daum.net/digital/others/newsview?newsid=20130531002404295 다운로더에 대한 처벌은 정하지 못 했고, 토렌트 SEED파일을 많이 올린 사람은 입건했고, 한번이라도 올린 사람 4만명의 정보를 확보했다는데, 원래 seed 파일에 올린 사람의 컴퓨터 정보가 들어가는 것인지 아니면 서버에 저장된 정보를 찾아서 보는 것인지 확인 해봐야 겠다. 

토렌트 파일(.torrent) 의 구조

Announce 섹션

“Tracker”의 URL 정보를 포함한다.

Info 섹션

파일의 이름, 길이, 파일 조각의 길이, 그리고 파일의 무결성을 진단하기 위한 각 조각의 SHA-1 해시 코드가 포함되어 있다. 파일을 다 받은 클라이언트는 Seeder 역할을 수행할 수 있어서 파일 공유의 효율을 높일 수 있다.

  • name - suggested file/directory name where the file(s) is/are to be saved
  • piece length - number of bytes per piece. This is commonly 28 = 256 KiB = 262,144 B.
  • pieces - a hash list. That is, a concatenation of each piece's SHA-1 hash. As SHA-1 returns a 160-bit hash, pieces will be a string whose length is a multiple of 160-bits.
  • length - size of the file in bytes (only when one file is being shared)
  • files - a list of dictionaries each corresponding to a file (only when multiple files are being shared). Each dictionary has the following keys:
    • path - a list of strings corresponding to subdirectory names, the last of which is the actual file name
    • length - size of the file in bytes.

파일 한 개 짜리…

{
    'announce': 'http://bttracker.debian.org:6969/announce',
    'info':
    {
        'name': 'debian-503-amd64-CD-1.iso',
        'piece length': 262144,
        'length': 678301696,
        'pieces': '841ae846bc5b6d7bd6e9aa3dd9e551559c82abc1...d14f1631d776008f83772ee170c42411618190a4'
    }
}

파일 두개 짜리

{
    'announce': 'http://tracker.site1.com/announce',
    'info':
    {
        'name': 'directoryName',
        'piece length': 262144,
        'files':
        [
            {'path': ['111.txt'], 'length': 111},
            {'path': ['222.txt'], 'length': 222}
        ],
        'pieces': '6a8af7eda90ba9f851831073c48ea6b7b7e9feeb...8a43d9d965a47f75488d3fb47d2c586337a20b9f'
    }
}

토렌트 정보 긁기

torrent.php
<?php
// 기본적으로 UTF-8 형식임.
// 출처: http://blog.yesyo.com/72
// Protect our namespace using a class
class BDecode {
    function numberdecode($wholefile, $offset) {
        // Funky handling of negative numbers and zero
        $negative = false;
        if ($wholefile[$offset] == '-') {
            $negative = true;
            $offset++;
        }
        if ($wholefile[$offset] == '0') {
            $offset++;
            if ($negative)
                return array(false);
            if ($wholefile[$offset] == ':' || $wholefile[$offset] == 'e')
                return array(0, ++$offset);
            return array(false);
        }
        $ret[0] = 0;
        for(;;) {
            if ($wholefile[$offset] >= '0' && $wholefile[$offset] <= '9') {
                $ret[0] *= 10;
                //Added 2005.02.21 - VisiGod
           //Changing the type of variable from integer to double to prevent a numeric overflow
                settype($ret[0],'double');
                //Added 2005.02.21 - VisiGod
                $ret[0] += ord($wholefile[$offset]) - ord('0');
                $offset++;
            }    else if ($wholefile[$offset] == 'e' || $wholefile[$offset] == ':') {
                // Tolerate : or e because this is a multiuse function
                $ret[1] = $offset+1;
                if ($negative) {
                    if ($ret[0] == 0)
                        return array(false);
                    $ret[0] = - $ret[0];
                }
                return $ret;
            } else return array(false);
        }
    }
 
    function decodeEntry($wholefile, $offset=0) {
        if ($wholefile[$offset] == 'd')
            return $this->decodeDict($wholefile, $offset);
        if ($wholefile[$offset] == 'l')
            return $this->decodelist($wholefile, $offset);
        if ($wholefile[$offset] == 'i')
            return $this->numberdecode($wholefile, ++$offset);
        // String value: decode number, then grab substring
 
        $info = $this->numberdecode($wholefile, $offset);
        if ($info[0] === false)
            return array(false);
        $ret[0] = substr($wholefile, $info[1], $info[0]);
        $ret[1] = $info[1]+strlen($ret[0]);
        return $ret;
    }
 
    function decodeList($wholefile, $offset) {
        if ($wholefile[$offset] != 'l')
            return array(false);
        $offset++;
        $ret = array();
        for ($i=0;;$i++) {
            if ($wholefile[$offset] == 'e')
                break;
            $value = $this->decodeEntry($wholefile, $offset);
            if ($value[0] === false)
                return array(false);
            $ret[$i] = $value[0];
            $offset = $value[1];
        }
        // The empty list is an empty array. Seems fine.
        return array(0=>$ret, 1=>++$offset);
    }
 
    // Tries to construct an array
    function decodeDict($wholefile, $offset=0) {
        if ($wholefile[$offset] == 'l')
            return $this->decodeList($wholefile, $offset);
        if ($wholefile[$offset] != 'd')
            return false;
        $ret=array();
        $offset++;
        for (;;) {
            if ($wholefile[$offset] == 'e')    {
                $offset++;
                break;
            }
            $left = $this->decodeEntry($wholefile, $offset);
            if (!$left[0])
                return false;
            $offset = $left[1];
            if ($wholefile[$offset] == 'd') {
                // Recurse
                $value = $this->decodedict($wholefile, $offset);
                if (!$value[0])
                    return false;
                $ret[addslashes($left[0])] = $value[0];
                $offset= $value[1];
                continue;
            }
            if ($wholefile[$offset] == 'l') {
                $value = $this->decodeList($wholefile, $offset);
                if (!$value[0] && is_bool($value[0]))
                    return false;
                $ret[addslashes($left[0])] = $value[0];
                $offset = $value[1];
                continue;
            }
            $value = $this->decodeEntry($wholefile, $offset);
            if ($value[0] === false)
                return false;
            $ret[addslashes($left[0])] = $value[0];
            $offset = $value[1];
        }
        return array(0=>(empty($ret)?true:$ret), 1=>$offset);
    }
} // End of class declaration.
 
// Use this function. eg:  BDecode("d8:announce44:http://www. ... e");
function BDecode($wholefile) {
    $decoder = new BDecode;
    $return = $decoder->decodeEntry($wholefile);
    return $return[0];
}
 
// We'll protect the namespace of our code
// using a class
class BEncode {
    // Dictionary keys must be sorted. foreach tends to iterate over the order
    // the array was made, so we make a new one in sorted order. :)
    function makeSorted($array) {
        // Shouldn't happen!
        if (empty($array))
            return $array;
        $i = 0;
        foreach($array as $key => $dummy)
            $keys[$i++] = stripslashes($key);
        sort($keys);
        for ($i=0; isset($keys[$i]); $i++)
            $return[addslashes($keys[$i])] = $array[addslashes($keys[$i])];
        return $return;
    }
 
    // Encodes strings, integers and empty dictionaries.
    // $unstrip is set to true when decoding dictionary keys
    function encodeEntry($entry, &$fd, $unstrip = false) {
        if (is_bool($entry)) {
            $fd .= 'de';
            return;
        }
        if (is_int($entry) || is_float($entry)) {
            $fd .= 'i'.$entry.'e';
            return;
        }
        if ($unstrip)
            $myentry = stripslashes($entry);
        else
            $myentry = $entry;
        $length = strlen($myentry);
        $fd .= $length.':'.$myentry;
    }
 
    // Encodes lists
    function encodeList($array, &$fd) {
        $fd .= 'l';
        // The empty list is defined as array();
        if (empty($array)) {
            $fd .= 'e';
            return;
        }
        for ($i = 0; isset($array[$i]); $i++)
            $this->decideEncode($array[$i], $fd);
        $fd .= 'e';
    }
 
    // Passes lists and dictionaries accordingly, and has encodeEntry handle
    // the strings and integers.
    function decideEncode($unknown, &$fd) {
        if (is_array($unknown)) {
            if (isset($unknown[0]) || empty($unknown))
                return $this->encodeList($unknown, $fd);
            else
                return $this->encodeDict($unknown, $fd);
        }
        $this->encodeEntry($unknown, $fd);
    }
 
    // Encodes dictionaries
    function encodeDict($array, &$fd) {
        $fd .= 'd';
        if (is_bool($array)) {
            $fd .= 'e';
            return;
        }
        // NEED TO SORT!
        $newarray = $this->makeSorted($array);
        foreach($newarray as $left => $right) {
            $this->encodeEntry($left, $fd, true);
            $this->decideEncode($right, $fd);
        }
        $fd .= 'e';
    }
} // End of class declaration.
 
// Use this function in your own code.
function BEncode($array) {
    $string = '';
    $encoder = new BEncode;
    $encoder->decideEncode($array, $string);
    return $string;
}
 
$url = trim($_GET[url]);
if ($url) {
        $alltorrent = trim(Yreadfile($url, ''));
} else exit;
if ($alltorrent == "") exit;
$array = BDecode($alltorrent);
 
$hash=sha1(BEncode($array["info"]));
echo "<b>MAGNET :</b> magnet:?xt=urn:btih:".$hash."<br />";
echo "<b>ANNOUNCE :</b> ".$array[announce]."<br />";
echo "<b>ANNOUNCE-LIST :</b> ";
$announce_list = "announce-list";
$announce_list_cnt = count($array[$announce_list]);
for ($i=0;$i < $announce_list_cnt;$i++) {
    echo $array[$announce_list][$i][0];
    if ($i < $announce_list_cnt-1)
        echo ", ";
    else
        echo "<br />";
}
 
echo "<b>COMMENT :</b> ".$array[comment]."<br />";
$creation_date = "creation date";
echo "<b>CREATION DATE :</b> ".date("Y-m-d",$array[$creation_date])."<br />";
echo "<b>NAME :</b> ".$array[info][name]."<br />";
$file_cnt = 0;
$info_files_cnt = count($array[info][files]);
for ($i=0;$i < $info_files_cnt;$i++) {
    $info_file_path_cnt = count($array[info][files][$i][path]);
    $file_cnt++;
    echo $file_cnt.": ";
    for ($j=0;$j < $info_file_path_cnt;$j++) {
        echo $array[info][files][$i][path][$j];
        if ($j < $info_file_path_cnt-1) echo "/";
        echo " (".$array[info][files][$i][length]."byte)";
    }
    echo "<br />";
}
 
/*
 아래 소켓방식으로 파일 가저오기는 유창화 님의 소스 이다.
 */
//변수가 정의 되었으면 해당 값을 반환하고 정의 되어있지 않으면 지정된 기본값을 반환한다.
function Yvar_check(&$var, $return=''){
        return (isset($var)) ? $var : $return;
}
 
//변수가 정의되지 않았거나 값이 NULL값 이거나, 값이 0, false 일경우 지정된 기본값을 반환한다.
function Yvar_empty_check(&$var, $return=''){
        return (!empty($var)) ? $var : $return;
}
 
//http, GET 방식의 소켓연결
function Ysockopen($url, $referer='', $accept='*/*', $contenttype='application/x-www-form-urlencoded', $cachecontrol='private', $pragma='no-cache', $connection='close'){
        if (!empty($url) && preg_match("`^http://.+`i", $url)) {
 
                $array = parse_url($url);
                $url_scheme = Yvar_check($array['scheme']);
                $url_server = Yvar_check($array['host']);
                $url_path = Yvar_check($array['path']);
                $url_query= Yvar_check($array['query']);
                $url_port = Yvar_empty_check($array['port'], 80);
 
                $fp = @fsockopen($url_server, $url_port);
 
            if (empty($fp)) {
                        return '';
            }
 
                fputs($fp, "GET " . $url_path . "?" . $url_query . " HTTP/1.0\n");
                if (!empty($accept)) fputs($fp, "Accept: " . $accept . "\n");
                if (!empty($contenttype)) fputs($fp, "Content-Type: " . $contenttype . "\n");
                fputs($fp, "Host: $url_server:$url_port\n");
                if (!empty($referer)) fputs($fp, "Referer: " . $referer . "\n");
                if (!empty($cachecontrol)) fputs($fp, "Cache-control: " . $cachecontrol . "\n");
                if (!empty($pragma)) fputs($fp, "Pragma: " . $pragma . "\n");
                if (!empty($connection)) fputs($fp, "Connection: " . $connection . "\n\n");
 
                return $fp;
        } else {
                return '';
        }
}
 
function Ysockclose(&$fp){
        if (!empty($fp)) fclose($fp);
        return true;
}
 
//소켓으로 외부파일 통째로 텍스트로 읽어옴
function Yreadfile($url, $referer='', $accept='*/*', $contenttype='application/x-www-form-urlencoded', $cachecontrol='private', $pragma='no-cache', $connection='close') {
        $fp = Ysockopen($url, $referer, $accept, $contenttype, $cachecontrol, $pragma, $connection);
        if (!empty($fp)) {
                $text = '';
                $check_header = false;
                while (!feof($fp)){
                        $temp = fgets($fp, 1024);
                        if ($check_header == false){
                                //실제 파일이 아닌 헤더 정보인지 체크 하여 추가하지 않는다.
                                if (preg_match("'^(\r)?\n$'", $temp)) {
                                        $check_header = true;
                                        continue;
                                }
                        } else{
                                //헤더 정보가 아닌 경우에만 추가한다.
                                $text .= $temp;
                        }
                }
                Ysockclose($fp);
                return $text;
        } else {
            return '';
        }
}
 
?>

연결문서

CC Attribution-Noncommercial-Share Alike 4.0 International 별도로 명시하지 않을 경우, 이 위키의 내용은 다음 라이선스에 따라 사용할 수 있습니다: CC Attribution-Noncommercial-Share Alike 4.0 International
18.8 KB tech/torrent.txt · 마지막으로 수정됨 2018/06/01 16:16 저자 59.152.173.242 V_L

0.113 seconds in processing this page on this powerful server.