Trình khách BitTorrent được tự triển khai từ đầu
(github.com/piyushgupta53)- Dự án mã nguồn mở này là một trình khách BitTorrent được triển khai bằng ngôn ngữ Go, tự hiện thực logic tải tệp cơ bản
- Tự xử lý mã hóa/giải mã Bencode, đồng thời bao gồm khả năng kiểm tra lỗi mạnh mẽ
- Hỗ trợ toàn diện các tính năng cốt lõi như phân tích tệp
.torrent, tính toán info hash, giao tiếp giữa các peer - Bao gồm các tính năng tăng tính thực tiễn như tải xuống đồng thời, ghép tệp, quản lý lưu trữ theo khối
- So với các mã nguồn mở BitTorrent hiện có, dự án có thế mạnh về sự đơn giản của Go, cấu trúc mã rõ ràng và tính mô-đun
Tổng quan
Dự án này tự triển khai một trình khách BitTorrent bằng Go
Nó cung cấp khả năng tải tệp sử dụng giao thức BitTorrent theo hình thức tự phát triển
Trọng tâm là các chức năng phân tích tệp torrent, khám phá peer và tải tệp
Tính năng chính
-
Mã hóa/giải mã Bencode
- Hỗ trợ mọi kiểu Bencode như chuỗi, số nguyên, danh sách và từ điển
- Áp dụng xử lý lỗi mạnh mẽ và kiểm tra dữ liệu
-
Xử lý tệp torrent
- Có thể phân tích cả torrent một tệp và nhiều tệp
- Trích xuất info hash và hash của từng piece, hỗ trợ mọi trường chuẩn
-
Khám phá và giao tiếp với peer
- Hỗ trợ HTTP tracker
- Triển khai giao thức bắt tay giữa các peer
- Thực hiện giao thức thông điệp BitTorrent và quản lý kết nối peer
-
Chức năng tải xuống
- Quản lý theo piece và block
- Xử lý tải xuống đồng thời
- Theo dõi tiến độ tải xuống và ghép tệp
- Cung cấp hiệu quả nhờ quản lý lưu trữ theo block
Cấu trúc dự án
- cmd/ : giao diện dòng lệnh và tệp thực thi
- internal/
- bencode/ : chức năng mã hóa và giải mã Bencode
- torrent/ : phân tích và xử lý tệp torrent
- tracker/ : triển khai giao thức tracker
- peer/ : chức năng giao tiếp giữa các peer
- download/ : chức năng quản lý tải xuống
- pkg/ : tập hợp các package có thể cung cấp ra bên ngoài
Yêu cầu
- Cần Go 1.21 trở lên
Cách sử dụng
- Hiện dự án vẫn đang ở giai đoạn phát triển ban đầu, hướng dẫn sử dụng sẽ được bổ sung sau
Tình trạng phát triển và kế hoạch
- Hiện đang được phát triển tích cực
- Các giai đoạn phát triển chi tiết được ghi trong tệp checkpoint.md
- Kế hoạch sắp tới:
- Hỗ trợ liên kết Magnet
- Giao thức trao đổi metadata
- Dự kiến hỗ trợ DHT (bảng băm phân tán)
Tài liệu tham khảo
- Đặc tả giao thức BitTorrent
- Đặc tả Bencode
Ý nghĩa và điểm mạnh của dự án
- Dự án tận dụng cú pháp đơn giản và khả năng song song đặc trưng của Go để triển khai các thành phần phức tạp của một trình khách BitTorrent theo cách mô-đun hóa rõ ràng
- Cấu trúc rõ ràng, dễ mở rộng và dễ bảo trì mang lại lợi ích cho cả việc học tập lẫn ứng dụng thực tế
- Dù vẫn ở giai đoạn tương đối sớm, dự án đã nhanh chóng hiện thực các chức năng cốt lõi của giao thức BitTorrent
1 bình luận
Ý kiến trên Hacker News
Có đề xuất nên giới hạn kích thước cấp phát bộ nhớ động trong bộ giải mã bencode. Vì dữ liệu đầu vào từ file torrent hoặc từ announce không đáng tin cậy, đầu vào độc hại có thể yêu cầu cấp phát rất lớn và gây từ chối dịch vụ (DoS). Với việc phân tích chuỗi, có thể đặt giới hạn trên hợp lý là độ dài phần đầu vào còn lại, vì một torrent hợp lệ không thể chứa chuỗi dài hơn phần còn lại của file
Dự án trông gọn gàng và đơn giản nên rất thích. Có vẻ sẽ tốt hơn nếu thêm ví dụ sử dụng một dòng vào Readme. Ví dụ, nên thêm một câu minh họa cách dùng như
./go-torrent My-Linux-Distro-Wink-ISO.torrent. Nếu còn thêm cả tính năngtorrent.ParseFromUrlthì càng được điểm hơn. Ai cũng nên thử trải nghiệm kiểu này một lần cho “hành trình tinh thần” của riêng mìnhGiới thiệu một thử thách tương tự do codecrafters cung cấp. Khóa này hỗ trợ theo dõi tiến trình và kiểm thử, và tôi đã thử miễn phí một tháng, khá thú vị
https://app.codecrafters.io/courses/bittorrent/overview
Không phải là lập trình viên Go nên tôi thắc mắc tại sao lại dùng phiên bản cũ Go 1.21. Có lý do đặc biệt nào để cố dùng bản cũ không? Tìm ra thì thấy đã hết hỗ trợ từ 10 tháng trước
Vì hỗ trợ Windows 7. Các dự án viết bằng Go 1.21.4 trở xuống chạy được trên gần như mọi bản Windows từ năm 2009 và hầu hết mọi máy tính, nhưng nếu dùng từ 1.21.5 trở lên thì chỉ chạy được trên máy mới và Windows 10, 11, mà lại không có lợi ích đặc biệt nào
https://github.com/golang/go/issues/64622
README có vẻ nhiều khả năng do AI viết. Trong file go.mod thực tế lại đặt phiên bản Go là 1.23.1, nên rốt cuộc sẽ cần 1.23.1 trở lên
https://github.com/piyushgupta53/go-torrent-client/blob/6130f4e/go.mod#L3 https://go.dev/doc/modules/gomod-ref#go-notes
Đây thực sự là một dự án rất tuyệt. Hồi đại học tôi từng làm cái này như bài tập cuối kỳ trong lớp mạng ở Georgia Tech; code thì đã mất rồi nhưng những bài học rút ra thì theo tôi cả đời. Những dự án như thế này là cách rất tốt để học một ngôn ngữ mới
Có người hỏi liệu nó có hỗ trợ magnet link không.
Edit: Giờ thì đã biết đó là tính năng sẽ được thêm trong tương lai
Tôi tò mò không biết bạn đã làm thứ này như thế nào. Bạn có tự đọc đặc tả giao thức không, hay tham khảo các triển khai khác? Tôi luôn thắc mắc người ta bắt đầu triển khai từ con số 0 kiểu này ra sao
https://www.bittorrent.org/beps/bep_0003.html
Các phần mở rộng bổ sung ở
https://www.bittorrent.org/beps/bep_0000.html
Điều quan trọng là chia công việc thành những phần thật nhỏ và tự kiểm chứng kết quả từng bước. Ví dụ, tôi bắt đầu từ việc phân tích file .torrent, và phải tự triển khai bencoding. Khi tải file .torrent của Arch Linux về thì lại thấy định dạng không hợp lệ, xuất hiện các khóa ngoài dự kiến như url-list. Tìm hiểu thêm thì hóa ra liên quan đến bep_0019. Cuối cùng tôi đã phân tích thành công file .torrent của Debian Linux
Sau đó tôi tiếp tục triển khai yêu cầu HTTP announce với tracker và cả giao thức peer. Giao thức peer khá khó, và cách tiếp cận thích thử nghiệm giúp ích rất nhiều. Tôi xóa announce URL khỏi torrent Debian để nó hoàn toàn không có peers, rồi thêm trực tiếp client của mình vào KTorrent để quan sát các thông điệp gửi qua lại, sau đó chỉnh code của mình theo những gì quan sát được. Có rất nhiều lần thử-sai và gỡ lỗi
Một số chi tiết giao thức nhỏ thì tôi hoàn toàn không tìm thấy trong tài liệu chính thức, nên đôi lúc cũng có hỏi ChatGPT chút ít; ngoài ra mỗi client lại triển khai hơi khác nhau nên các thuật toán chi tiết không thật sự rõ ràng. Ví dụ như chọn block nào để nhận, kết nối với peer nào, choke/unchoke hoạt động ra sao... đều không được tổng kết tử tế. Tìm kiếm trên web giúp ích rất nhiều
Ngoài ra trang https://wiki.theory.org/Main_Page cũng có khá nhiều thông tin hữu ích
Hiện giờ nó đã ở mức có thể tải xuống/tải lên hoàn chỉnh với KTorrent. Bước tiếp theo là lấy peer từ tracker, xây dựng thuật toán chọn block để tải và ghi chúng vào file
Nếu muốn hỏi sâu hơn về quá trình chi tiết thì cứ hỏi tiếp
Có người hỏi việc thêm GUI sẽ khó đến mức nào. Tôi hiếm khi thấy ví dụ làm GUI bằng Go
Cá nhân tôi thích https://github.com/AllenDang/giu, một wrapper của ImGui
Nhiều tính năng nhất có lẽ là unison, nhưng tôi không rõ nó có thật sự được dùng rộng rãi không, và tài liệu có vẻ rất thiếu https://github.com/richardwilkes/unison
Gio là một framework GUI theo hướng mới, được dùng trong Tailscale và gotraceui https://gioui.org
Wails thì dễ học nếu bạn có kinh nghiệm phát triển web https://wails.io
Binding GTK4 cũng có vẻ ổn https://github.com/diamondburned/gotk4
Cogent Core cũng trông khá thú vị, nhưng tôi chỉ dùng thử trong thời gian ngắn trước khi chuyển sang ngôn ngữ Odin thay vì Go https://www.cogentcore.org/core
Cá nhân tôi gặp khá nhiều vấn đề hiệu năng với Fyne trên nhiều máy và nhiều hệ điều hành, nhưng dù sao đây vẫn là framework GUI nổi tiếng nhất https://fyne.io
Tôi từng nghĩ có thể thử làm một dự án như thế này vì cũng quan tâm. Tôi muốn biết nó khó đến đâu và bạn đánh giá mức độ hoàn thiện hiện tại thế nào, liệu đã triển khai các tính năng phức tạp như DHT, Magnet, NAT traversal chưa. Thực ra tôi cũng không rõ để bao phủ được gần như mọi torrent ngoài đời thì chính xác cần những tính năng nào. Có quá nhiều giao thức liên quan đến torrent nên tôi còn không biết đầy đủ danh sách, chứ chưa nói đến việc hiểu từng giao thức làm gì
Mức độ khó thay đổi rất nhiều tùy kinh nghiệm, mức độ thành thạo ngôn ngữ và thói quen thử nghiệm. Ví dụ như tôi cũng mới bắt đầu viết Bittorrent client bằng Go từ tuần trước, vậy mà chỉ sau một tuần đã làm được khoảng 80% so với dự án được đăng ở đây. Tôi tiến triển nhanh vì có nhiều kiến thức về Go, giao thức, mạng và quen với việc thử nghiệm
Bản thân đặc tả chính thức của Bittorrent thật ra rất ngắn, có thể đọc và hiểu trong khoảng một giờ https://www.bittorrent.org/beps/bep_0003.html
Nhưng các giao thức mở rộng xung quanh thì rất nhiều, và mức độ hỗ trợ lại khác nhau giữa các client. Ví dụ, nhiều nơi sẽ thử mã hóa giao thức trước (thực tế là làm rối) rồi nếu không được mới quay về giao thức thường
Nếu bạn chỉ muốn tải các file chính thức như bản phân phối Linux từ file .torrent chính thức thì độ khó chắc chắn thấp hơn. Thường chỉ là một file, có tracker, và phần lớn peer dùng giao thức chuẩn, nên ngay cả trong môi trường NAT cũng vẫn hoạt động đủ tốt mà không cần mở cổng nội bộ
Tất nhiên, nếu muốn hỗ trợ torrent phổ thông hơn (đặc biệt là ở vùng xám) thì sẽ dần phải thêm phân tích magnet link, DHT để tìm peer, và UPnP để tự động ánh xạ cổng. Nhưng ngay cả như vậy, bạn vẫn có thể chia nhỏ và triển khai từng tính năng một theo từng bước. Càng nhiều tính năng thì càng tìm được nhiều peer hơn và trao đổi thành công hơn
Nó khá thử thách; tôi mất gần một tháng để học giao thức và cách bencoding hoạt động, hình dung toàn bộ cấu trúc trong đầu rồi mới viết code. Hiện vẫn chưa hỗ trợ Magnet và DHT
Có người hỏi liệu đã triển khai v2 và mutable torrents chưa. Đồng thời bày tỏ mong muốn nhất định hãy hỗ trợ mutable torrents