diff --git a/nex-be/pom.xml b/nex-be/pom.xml index 39fe7c4..5493fb1 100644 --- a/nex-be/pom.xml +++ b/nex-be/pom.xml @@ -87,6 +87,13 @@ provided + + + com.turn + ttorrent-core + 1.5 + + diff --git a/nex-be/src/main/java/com/unisinsight/project/tb/JavaSeeder.java b/nex-be/src/main/java/com/unisinsight/project/tb/JavaSeeder.java new file mode 100644 index 0000000..71fca45 --- /dev/null +++ b/nex-be/src/main/java/com/unisinsight/project/tb/JavaSeeder.java @@ -0,0 +1,36 @@ +package com.unisinsight.project.tb; + +import com.turn.ttorrent.client.Client; +import com.turn.ttorrent.client.SharedTorrent; + +import java.io.File; +import java.net.InetAddress; + +public class JavaSeeder { + public static void main(String[] args) throws Exception { + // 1. 种子文件和原始文件 + File torrentFile = new File("4.txt.torrent"); // 输出的种子文件 + File file = new File("D:\\temp\\log\\3.txt"); // 要共享的文件 +// + String trackerUrl = "udp://tracker.openbittorrent.com:80/announce"; // Tracker URL + TorrentCreator111.createTorrent(file, trackerUrl, torrentFile); + System.out.println("Torrent file created successfully: " + torrentFile.getAbsolutePath()); + + // 1. 加载种子和文件 + SharedTorrent torrent = SharedTorrent.fromFile( + torrentFile, + file.getParentFile() + ); + + // 2. 创建客户端并启用 DHT + Client client = new Client( + InetAddress.getLocalHost(), // 绑定本机 IP + torrent + ); + + // 3. 开始做种 + client.share(); + System.out.println("DHT 做种已启动..."); + + } +} \ No newline at end of file diff --git a/nex-be/src/main/java/com/unisinsight/project/tb/TorrentCreator111.java b/nex-be/src/main/java/com/unisinsight/project/tb/TorrentCreator111.java new file mode 100644 index 0000000..6e8056c --- /dev/null +++ b/nex-be/src/main/java/com/unisinsight/project/tb/TorrentCreator111.java @@ -0,0 +1,138 @@ +package com.unisinsight.project.tb; + +import java.io.*; +import java.nio.file.Files; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class TorrentCreator111 { + private static final int PIECE_LENGTH = 256 * 1024; // 256KB 分块大小 + + public static void createTorrent(File file, String announceUrl, File outputTorrent) + throws IOException, NoSuchAlgorithmException { + // 计算文件哈希 + List pieceHashes = calculatePieceHashes(file); + + // 构建info字典 + Map info = new HashMap<>(); + info.put("name", file.getName()); + info.put("piece length", PIECE_LENGTH); + info.put("pieces", concatenateHashes(pieceHashes)); + info.put("length", file.length()); + + // 构建整个torrent字典 + Map torrent = new HashMap<>(); + torrent.put("announce", announceUrl); + torrent.put("info", info); + + // 编码并写入文件 + byte[] torrentData = Bencode.encode(torrent); + try (FileOutputStream fos = new FileOutputStream(outputTorrent)) { + fos.write(torrentData); + } + } + + private static List calculatePieceHashes(File file) + throws IOException, NoSuchAlgorithmException { + List pieceHashes = new ArrayList<>(); + MessageDigest sha1 = MessageDigest.getInstance("SHA-1"); + + try (InputStream is = Files.newInputStream(file.toPath())) { + byte[] buffer = new byte[PIECE_LENGTH]; + int bytesRead; + + while ((bytesRead = is.read(buffer)) != -1) { + sha1.reset(); + sha1.update(buffer, 0, bytesRead); + pieceHashes.add(sha1.digest()); + } + } + + return pieceHashes; + } + + private static byte[] concatenateHashes(List pieceHashes) { + byte[] result = new byte[pieceHashes.size() * 20]; // SHA-1哈希是20字节 + int offset = 0; + + for (byte[] hash : pieceHashes) { + System.arraycopy(hash, 0, result, offset, hash.length); + offset += hash.length; + } + + return result; + } + + // Bencode编码工具类 + private static class Bencode { + public static byte[] encode(Object obj) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + encode(obj, baos); + return baos.toByteArray(); + } + + private static void encode(Object obj, OutputStream out) throws IOException { + if (obj instanceof String) { + encodeString((String) obj, out); + } else if (obj instanceof Integer || obj instanceof Long) { + encodeInteger(((Number) obj).longValue(), out); + } else if (obj instanceof Map) { + encodeDictionary((Map) obj, out); + } else if (obj instanceof List) { + encodeList((List) obj, out); + } else if (obj instanceof byte[]) { + encodeBytes((byte[]) obj, out); + } else { + throw new IllegalArgumentException("Unsupported type: " + obj.getClass()); + } + } + + private static void encodeString(String s, OutputStream out) throws IOException { + out.write((s.length() + ":").getBytes()); + out.write(s.getBytes()); + } + + private static void encodeInteger(long i, OutputStream out) throws IOException { + out.write(("i" + i + "e").getBytes()); + } + + private static void encodeDictionary(Map dict, OutputStream out) throws IOException { + out.write('d'); + for (Map.Entry entry : dict.entrySet()) { + encode(entry.getKey().toString(), out); + encode(entry.getValue(), out); + } + out.write('e'); + } + + private static void encodeList(List list, OutputStream out) throws IOException { + out.write('l'); + for (Object item : list) { + encode(item, out); + } + out.write('e'); + } + + private static void encodeBytes(byte[] bytes, OutputStream out) throws IOException { + out.write((bytes.length + ":").getBytes()); + out.write(bytes); + } + } + + public static void main(String[] args) { + try { + File fileToShare = new File("D:\\temp\\log\\2.txt"); // 要共享的文件 + String trackerUrl = "http://tracker.openbittorrent.com:80/announce"; // Tracker URL + File torrentFile = new File("2.txt.torrent"); // 输出的种子文件 + + createTorrent(fileToShare, trackerUrl, torrentFile); + System.out.println("Torrent file created successfully: " + torrentFile.getAbsolutePath()); + } catch (Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file