{"id":30921,"date":"2025-10-03T12:31:55","date_gmt":"2025-10-03T09:31:55","guid":{"rendered":"https:\/\/fatihsoysal.com\/blog\/spring-boot-ve-jlibtorrent-ile-java-torrent-sunucusu-nasil-yapilir\/"},"modified":"2025-10-03T12:31:55","modified_gmt":"2025-10-03T09:31:55","slug":"spring-boot-ve-jlibtorrent-ile-java-torrent-sunucusu-nasil-yapilir","status":"publish","type":"post","link":"https:\/\/fatihsoysal.com\/blog\/spring-boot-ve-jlibtorrent-ile-java-torrent-sunucusu-nasil-yapilir\/","title":{"rendered":"Spring Boot ve JLibtorrent ile Java Torrent Sunucusu Nas\u0131l Yap\u0131l\u0131r?"},"content":{"rendered":"<p><body><\/p>\n<style>\n  \/* Mobil uyumlu aray\u00fcz i\u00e7in temel CSS yakla\u015f\u0131mlar\u0131 *\/\n  .container {\n    max-width: 960px;\n    margin: 0 auto;\n    padding: 20px;\n  }<\/p>\n<p>  .box {\n    background-color: #f0f8ff;\n    border-left: 5px solid #007bff;\n    padding: 15px;\n    margin-bottom: 20px;\n    color: #333;\n  }<\/p>\n<p>  @media (max-width: 768px) {\n    .container {\n      padding: 10px;\n    }\n    h2 {\n      font-size: 1.5em;\n    }\n    h3 {\n      font-size: 1.2em;\n    }\n    \/* Daha k\u00fc\u00e7\u00fck ekranlar i\u00e7in spesifik d\u00fczenlemeler *\/\n    .torrent-list {\n      display: block; \/* Yan yana duran elemanlar\u0131 alt alta getir *\/\n    }\n    .torrent-item {\n      width: 100%;\n      margin-bottom: 10px;\n    }\n  }<\/p>\n<p>  \/* Uzman \u0130pucu kutusu stilizasyonu *\/\n  .expert-tip {\n    background-color: #fff3cd; \/* Sar\u0131ms\u0131 arka plan *\/\n    border-left: 5px solid #ffc107; \/* Sar\u0131 sol kenarl\u0131k *\/\n    padding: 15px;\n    margin: 20px 0;\n    color: #664d03; \/* Koyu sar\u0131ms\u0131 metin rengi *\/\n    font-style: italic;\n    box-shadow: 0 2px 4px rgba(0,0,0,0.1);\n  }\n<\/style>\n<div class=\"container\">\n<p>P2P (Peer-to-Peer) dosya payla\u015f\u0131m\u0131 d\u00fcnyas\u0131nda kendi sunucunuzu kurarak veri aktar\u0131m\u0131n\u0131 kontrol etmek ister miydiniz? \u00d6zellikle b\u00fcy\u00fck veri setlerinin da\u011f\u0131t\u0131m\u0131nda veya ki\u015fisel bulut \u00e7\u00f6z\u00fcmlerinde, Java&#8217;n\u0131n g\u00fcc\u00fcn\u00fc Spring Boot&#8217;un esnekli\u011fi ve JLibtorrent&#8217;in yetenekleriyle birle\u015ftirerek \u00f6zel bir torrent sunucusu olu\u015fturabilirsiniz. Bu kapsaml\u0131 rehberde, s\u0131f\u0131rdan ad\u0131m ad\u0131m kendi Java torrent sunucunuzu nas\u0131l in\u015fa edece\u011finizi \u00f6\u011frenecek, teorik bilgilerden pratik kod \u00f6rneklerine kadar her detay\u0131 ke\u015ffedeceksiniz.<\/p>\n<p>G\u00fcn\u00fcm\u00fcz dijital d\u00fcnyas\u0131nda b\u00fcy\u00fck dosyalar\u0131n g\u00fcvenli ve verimli bir \u015fekilde payla\u015f\u0131lmas\u0131, hem bireysel kullan\u0131c\u0131lar hem de kurumsal yap\u0131lar i\u00e7in kritik bir ihtiya\u00e7 haline gelmi\u015ftir. Geleneksel merkezi sunucular\u0131n aksine, torrent protokol\u00fc da\u011f\u0131t\u0131k yap\u0131s\u0131 sayesinde dosya payla\u015f\u0131m\u0131n\u0131 \u00e7ok daha esnek ve dayan\u0131kl\u0131 bir hale getirir. Ancak mevcut torrent istemcilerinin sundu\u011fu \u00f6zellikler bazen s\u0131n\u0131rl\u0131 kalabilir veya \u00f6zel kullan\u0131m senaryolar\u0131na tam olarak uyum sa\u011flayamayabilir. \u0130\u015fte tam da bu noktada, kendi Java tabanl\u0131 torrent sunucunuzu Spring Boot ve JLibtorrent ile in\u015fa etmek devreye giriyor.<\/p>\n<p>Kendi sunucunuzu kurmak, size veri aktar\u0131m s\u00fcre\u00e7leri \u00fczerinde tam kontrol sa\u011flar. \u00d6rne\u011fin, sadece belirli kullan\u0131c\u0131lar\u0131n eri\u015febilece\u011fi \u00f6zel bir dosya payla\u015f\u0131m a\u011f\u0131 olu\u015fturabilir, indirme ve y\u00fckleme h\u0131zlar\u0131n\u0131 optimize edebilir veya mevcut sistemlerinizle entegre edebilece\u011finiz \u00f6zel API&#8217;ler geli\u015ftirebilirsiniz. Bu, \u00f6zellikle b\u00fcy\u00fck yaz\u0131l\u0131m g\u00fcncellemelerinin da\u011f\u0131t\u0131m\u0131, bilimsel veri setlerinin payla\u015f\u0131m\u0131 veya medya ak\u0131\u015f\u0131 hizmetleri gibi alanlarda b\u00fcy\u00fck avantajlar sunar. Ayr\u0131ca, kendi sunucunuz \u00fczerinde \u00e7al\u0131\u015fmak, protokol\u00fcn derinliklerini anlama ve performans\u0131 ihtiya\u00e7lar\u0131n\u0131za g\u00f6re ince ayar yapma f\u0131rsat\u0131 da verir. Bu s\u00fcre\u00e7te \u00f6\u011frenece\u011finiz Spring Boot ve JLibtorrent becerileri, Java ekosistemindeki di\u011fer da\u011f\u0131t\u0131k sistem projelerinde de size yol g\u00f6sterecektir.<\/p>\n<p>Peki, bu kadar \u00f6zelle\u015ftirilmi\u015f bir \u00e7\u00f6z\u00fcm\u00fcn hangi senaryolarda hayat kurtar\u0131c\u0131 olabilece\u011fine dair bir \u00f6rnek verelim: Bir yaz\u0131l\u0131m \u015firketinin d\u00fc\u015f\u00fcn\u00fcn ki, d\u00fcnya genelindeki binlerce m\u00fc\u015fterisine her ay 10GB boyutunda bir g\u00fcncellemeyi ula\u015ft\u0131rmas\u0131 gerekiyor. Merkezi bir sunucu \u00fczerinden bu kadar b\u00fcy\u00fck bir veri y\u00fck\u00fcn\u00fc y\u00f6netmek, hem bant geni\u015fli\u011fi maliyetlerini art\u0131r\u0131r hem de sunucu yo\u011funlu\u011funu beraberinde getirerek indirme s\u00fcrelerini uzatabilir. Ancak \u015firket, kendi Java torrent sunucusunu kullanarak bu g\u00fcncellemeleri P2P a\u011f\u0131 \u00fczerinden da\u011f\u0131tabilir. Her bir m\u00fc\u015fterinin istemcisi ayn\u0131 zamanda bir y\u00fckleyici (seeder) g\u00f6revi g\u00f6rerek a\u011f \u00fczerindeki y\u00fck\u00fc hafifletir, b\u00f6ylece hem sunucu maliyetleri d\u00fc\u015fer hem de kullan\u0131c\u0131lar \u00e7ok daha h\u0131zl\u0131 ve kesintisiz bir g\u00fcncelleme deneyimi ya\u015far. Bu, hem maliyet etkinli\u011fi hem de operasyonel verimlilik a\u00e7\u0131s\u0131ndan ciddi bir fark yarat\u0131r.<\/p>\n<h2>Torrent Protokol\u00fc ve JLibtorrent&#8217;in Temel \u0130\u015fleyi\u015fi Nas\u0131l Anla\u015f\u0131l\u0131r?<\/h2>\n<p>Torrent, asl\u0131nda dosyalar\u0131n k\u00fc\u00e7\u00fck par\u00e7alara b\u00f6l\u00fcnerek birden fazla kaynak (peer) aras\u0131nda e\u015f zamanl\u0131 olarak indirilip y\u00fcklenmesini sa\u011flayan bir ileti\u015fim protokol\u00fcd\u00fcr. Geleneksel HTTP indirmelerinden farkl\u0131 olarak, bir dosya ne kadar \u00e7ok ki\u015fi taraf\u0131ndan indirilirse, o kadar \u00e7ok kaynak taraf\u0131ndan y\u00fcklendi\u011fi i\u00e7in indirme h\u0131z\u0131 potansiyel olarak artar. Bu P2P modeli, merkezi sunucular\u0131n tek nokta ba\u015far\u0131s\u0131zl\u0131\u011f\u0131 riskini ortadan kald\u0131r\u0131r ve geni\u015f \u00f6l\u00e7ekli dosya da\u011f\u0131t\u0131m\u0131n\u0131 \u00e7ok daha sa\u011flam hale getirir.<\/p>\n<p>Bir torrent i\u015fleminin temel bile\u015fenleri \u015funlard\u0131r:<\/p>\n<ul>\n<li><strong>Torrent Dosyas\u0131 (.torrent):<\/strong> \u0130ndirilecek dosyan\u0131n ad\u0131, boyutu, par\u00e7alar\u0131 (pieces) ve her par\u00e7an\u0131n SHA-1 hash de\u011feri gibi meta verilerini i\u00e7erir. Ayr\u0131ca, a\u011fdaki di\u011fer kaynaklar\u0131 bulmak i\u00e7in kullan\u0131lan tracker sunucular\u0131n\u0131n adreslerini de bar\u0131nd\u0131rabilir.<\/li>\n<li><strong>Tracker:<\/strong> Peer&#8217;lar (e\u015fler) aras\u0131ndaki ba\u011flant\u0131lar\u0131 koordine eden merkezi bir sunucudur. Hangi peer&#8217;\u0131n hangi par\u00e7aya sahip oldu\u011funu kaydeder ve yeni ba\u011flanan peer&#8217;lara di\u011fer peer&#8217;lar\u0131n adreslerini sa\u011flar. Ancak modern torrent d\u00fcnyas\u0131nda DHT (Distributed Hash Table) gibi merkeziyetsiz mekanizmalar da tracker&#8217;lar\u0131n rol\u00fcn\u00fc \u00fcstlenmektedir.<\/li>\n<li><strong>Peer (E\u015f):<\/strong> Torrent a\u011f\u0131na ba\u011fl\u0131 olan herhangi bir istemci. Hem dosya par\u00e7alar\u0131n\u0131 indirip hem de di\u011fer peer&#8217;lara y\u00fckleyebilir.<\/li>\n<li><strong>Seeder (Y\u00fckleyici):<\/strong> Dosyan\u0131n tamam\u0131na sahip olan ve onu di\u011fer peer&#8217;lara y\u00fckleyen istemci.<\/li>\n<li><strong>Leecher (\u0130ndirici):<\/strong> Dosyan\u0131n tamam\u0131na hen\u00fcz sahip olmayan ve onu indirmeye \u00e7al\u0131\u015fan istemci.<\/li>\n<\/ul>\n<p>JLibtorrent ise, pop\u00fcler ve y\u00fcksek performansl\u0131 C++ tabanl\u0131 libtorrent-rasterbar k\u00fct\u00fcphanesinin Java ba\u011flay\u0131c\u0131s\u0131d\u0131r. Bu k\u00fct\u00fcphane, torrent protokol\u00fcn\u00fcn t\u00fcm karma\u015f\u0131k detaylar\u0131n\u0131 (DHT, PEX, UPnP, NAT-PMP gibi) soyutlayarak Java geli\u015ftiricilerinin kolayca torrent uygulamalar\u0131 olu\u015fturmas\u0131na olanak tan\u0131r. JLibtorrent&#8217;i kullanmak, platformlar aras\u0131 uyumluluk ve Java&#8217;n\u0131n g\u00fc\u00e7l\u00fc sanal makine (JVM) \u00f6zelliklerinden yararlanma avantaj\u0131 sunar. C++&#8217;dan JNI (Java Native Interface) arac\u0131l\u0131\u011f\u0131yla ba\u011flanan JLibtorrent, performanstan \u00f6d\u00fcn vermeden torrent i\u015flevselli\u011fini Java uygulamalar\u0131n\u0131za entegre etmenizi sa\u011flar.<\/p>\n<p>\u00d6rne\u011fin, JLibtorrent ile bir torrent oturumu ba\u015flatabilir, mevcut bir torrent dosyas\u0131n\u0131 ekleyebilir, indirme ve y\u00fckleme ilerlemesini takip edebilir, hatta kendi torrent dosyalar\u0131n\u0131z\u0131 olu\u015fturabilirsiniz. Bu k\u00fct\u00fcphane, sadece bir dosya indirme arac\u0131 olman\u0131n \u00f6tesinde, tam te\u015fekk\u00fcll\u00fc bir torrent istemcisi veya sunucusu olu\u015fturmak i\u00e7in gerekli t\u00fcm API&#8217;leri sunar. Bu esneklik, \u00f6zelle\u015ftirilmi\u015f bir Java torrent sunucusu olu\u015fturma hedefimiz i\u00e7in onu ideal bir se\u00e7im haline getirir.<\/p>\n<div class=\"expert-tip\">\n    Uzman \u0130pucu: JLibtorrent&#8217;in dahili DHT (Distributed Hash Table) ve PEX (Peer Exchange) mekanizmalar\u0131 sayesinde, \u00e7o\u011fu durumda harici bir tracker sunucusuna ba\u011f\u0131ml\u0131 kalmadan peer ke\u015ffi yapabilirsiniz. Bu, sunucunuzun daha merkeziyetsiz ve diren\u00e7li olmas\u0131n\u0131 sa\u011flar.\n  <\/div>\n<h2>Spring Boot ile Java Torrent Sunucusu Projesini Nas\u0131l Yap\u0131land\u0131r\u0131rs\u0131n\u0131z?<\/h2>\n<p>Spring Boot, Java uygulamalar\u0131n\u0131 h\u0131zl\u0131 bir \u015fekilde geli\u015ftirmek i\u00e7in pop\u00fcler bir \u00e7er\u00e7evedir. Otomatik yap\u0131land\u0131rma, dahili sunucu (Tomcat, Jetty) ve starter ba\u011f\u0131ml\u0131l\u0131klar\u0131 gibi \u00f6zellikleriyle geli\u015ftirme s\u00fcrecini b\u00fcy\u00fck \u00f6l\u00e7\u00fcde h\u0131zland\u0131r\u0131r. Torrent sunucumuzun temelini Spring Boot \u00fczerinde kurarak, RESTful API&#8217;ler arac\u0131l\u0131\u011f\u0131yla torrent y\u00f6netimi i\u015flevselli\u011fini kolayca sunabilir ve di\u011fer sistemlerle entegrasyonu basitle\u015ftirebiliriz.<\/p>\n<h3>Maven Ba\u011f\u0131ml\u0131l\u0131klar\u0131 ve Temel Spring Boot Yap\u0131s\u0131<\/h3>\n<p>\u00d6ncelikle, yeni bir Spring Boot projesi olu\u015ftural\u0131m. Bunun i\u00e7in <a href=\"https:\/\/start.spring.io\/\">Spring Initializr<\/a> kullanmak en kolay yoldur. Projenize eklemeniz gereken temel ba\u011f\u0131ml\u0131l\u0131klar \u015funlard\u0131r:<\/p>\n<ul>\n<li><strong>Spring Web:<\/strong> RESTful API&#8217;ler olu\u015fturmak i\u00e7in.<\/li>\n<li><strong>JLibtorrent:<\/strong> Torrent i\u015flevselli\u011fini sa\u011flamak i\u00e7in. Bu ba\u011f\u0131ml\u0131l\u0131k genellikle JCenter veya \u00f6zel bir Maven deposundan \u00e7ekilir.<\/li>\n<\/ul>\n<p><code>pom.xml<\/code> dosyan\u0131z a\u015fa\u011f\u0131daki gibi g\u00f6r\u00fcnmelidir (JLibtorrent versiyonu g\u00fcncelleyebilir):<\/p>\n<pre><code>\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http:\/\/maven.apache.org\/POM\/4.0.0\" xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\n         xsi:schemaLocation=\"http:\/\/maven.apache.org\/POM\/4.0.0 https:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0<\/modelVersion>\n    <parent>\n        <groupId>org.springframework.boot<\/groupId>\n        <artifactId>spring-boot-starter-parent<\/artifactId>\n        <version>3.2.5<\/version> <!-- G\u00fcncel Spring Boot versiyonu kullan\u0131n -->\n        <relativePath\/> <!-- lookup parent from repository -->\n    <\/parent>\n    <groupId>com.example<\/groupId>\n    <artifactId>java-torrent-server<\/artifactId>\n    <version>0.0.1-SNAPSHOT<\/version>\n    <name>java-torrent-server<\/name>\n    <description>Spring Boot Torrent Server with JLibtorrent<\/description>\n    <properties>\n        <java.version>17<\/java.version>\n    <\/properties>\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot<\/groupId>\n            <artifactId>spring-boot-starter-web<\/artifactId>\n        <\/dependency>\n\n        <!-- JLibtorrent ba\u011f\u0131ml\u0131l\u0131\u011f\u0131 -->\n        <dependency>\n            <groupId>com.frostwire<\/groupId>\n            <artifactId>jlibtorrent<\/artifactId>\n            <version>1.2.9.0<\/version> <!-- G\u00fcncel JLibtorrent versiyonu kullan\u0131n -->\n        <\/dependency>\n\n        <!-- Test ba\u011f\u0131ml\u0131l\u0131klar\u0131 -->\n        <dependency>\n            <groupId>org.springframework.boot<\/groupId>\n            <artifactId>spring-boot-starter-test<\/artifactId>\n            <scope>test<\/scope>\n        <\/dependency>\n    <\/dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot<\/groupId>\n                <artifactId>spring-boot-maven-plugin<\/artifactId>\n            <\/plugin>\n        <\/plugins>\n    <\/build>\n\n    <!-- JLibtorrent i\u00e7in gerekli repository -->\n    <repositories>\n        <repository>\n            <id>jcenter<\/id&gt;\n            <url>https:\/\/jcenter.bintray.com\/<\/url>\n        <\/repository>\n    <\/repositories>\n\n<\/project>\n  <\/pre>\n<p><\/code><\/p>\n<p>Ana Spring Boot uygulaman\u0131z klasik bir yap\u0131ya sahip olacakt\u0131r:<\/p>\n<pre><code>\npackage com.example.javatorrentserver;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class JavaTorrentServerApplication {\n\n    public static void main(String[] args) {\n        SpringApplication.run(JavaTorrentServerApplication.class, args);\n    }\n\n}\n  <\/pre>\n<p><\/code><\/p>\n<h3>JLibtorrent Oturum Y\u00f6netimi Nas\u0131l Kurulur?<\/h3>\n<p>JLibtorrent ile \u00e7al\u0131\u015fmaya ba\u015flamak i\u00e7in \u00f6ncelikle bir <code>Session<\/code> nesnesi olu\u015fturman\u0131z gerekir. Bu oturum, t\u00fcm torrent aktivitelerini y\u00f6netecek ana aray\u00fczd\u00fcr. Genellikle uygulaman\u0131n ya\u015fam d\u00f6ng\u00fcs\u00fcyle ba\u011flant\u0131l\u0131 olarak tek bir oturum olu\u015fturulur ve y\u00f6netilir. Spring Boot ba\u011flam\u0131nda, bu oturumu bir Spring <code>@Service<\/code> veya <code>@Component<\/code> olarak tan\u0131mlayabiliriz.<\/p>\n<p>A\u015fa\u011f\u0131daki gibi bir <code>TorrentService<\/code> s\u0131n\u0131f\u0131 olu\u015fturarak JLibtorrent oturumunu y\u00f6netebiliriz:<\/p>\n<pre><code>\npackage com.example.javatorrentserver.service;\n\nimport com.frostwire.jlibtorrent.AlertListener;\nimport com.frostwire.jlibtorrent.Session;\nimport com.frostwire.jlibtorrent.alerts.Alert;\nimport com.frostwire.jlibtorrent.alerts.AlertType;\nimport com.frostwire.jlibtorrent.alerts.TorrentFinishedAlert;\nimport jakarta.annotation.PostConstruct;\nimport jakarta.annotation.PreDestroy;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Service;\n\nimport java.io.File;\nimport java.util.concurrent.CountDownLatch;\n\n@Service\npublic class TorrentService {\n\n    private static final Logger log = LoggerFactory.getLogger(TorrentService.class);\n    private Session session;\n\n    @PostConstruct\n    public void init() {\n        log.info(\"JLibtorrent oturumu ba\u015flat\u0131l\u0131yor...\");\n        \/\/ JLibtorrent oturumunu ba\u015flat\n        session = new Session();\n\n        \/\/ Varsay\u0131lan olarak DHT'yi etkinle\u015ftir\n        session.startDht();\n        log.info(\"DHT ba\u015flat\u0131ld\u0131.\");\n\n        \/\/ Alert dinleyicisini ekle\n        session.addListener(new AlertListener() {\n            @Override\n            public int[] types() {\n                \/\/ \u0130lgilenilen alert tipleri\n                return new int[]{\n                    AlertType.TORRENT_FINISHED.swig(),\n                    AlertType.STATE_CHANGED.swig(),\n                    AlertType.LISTEN_SUCCEEDED.swig(),\n                    AlertType.LOG.swig()\n                };\n            }\n\n            @Override\n            public void alert(Alert<?> alert) {\n                switch (alert.type()) {\n                    case TORRENT_FINISHED:\n                        TorrentFinishedAlert tfa = (TorrentFinishedAlert) alert;\n                        log.info(\"Torrent indirme tamamland\u0131: {}\", tfa.torrentInfo().name());\n                        break;\n                    case LISTEN_SUCCEEDED:\n                        log.info(\"JLibtorrent dinleme ba\u015far\u0131l\u0131: {}\", alert.message());\n                        break;\n                    case LOG:\n                        \/\/ log.debug(\"JLibtorrent Log: {}\", alert.message());\n                        break;\n                    default:\n                        \/\/ log.debug(\"JLibtorrent Alert: {}\", alert.message());\n                        break;\n                }\n            }\n        });\n        log.info(\"JLibtorrent oturumu ba\u015far\u0131yla ba\u015flat\u0131ld\u0131.\");\n    }\n\n    @PreDestroy\n    public void destroy() {\n        if (session != null) {\n            log.info(\"JLibtorrent oturumu durduruluyor...\");\n            session.stop();\n            \/\/ Oturumun tamamen durmas\u0131n\u0131 beklemek i\u00e7in k\u0131sa bir s\u00fcre bekleyebiliriz\n            try {\n                Thread.sleep(1000); \/\/ 1 saniye beklet\n            } catch (InterruptedException e) {\n                Thread.currentThread().interrupt();\n            }\n            log.info(\"JLibtorrent oturumu durduruldu.\");\n        }\n    }\n\n    public Session getSession() {\n        return session;\n    }\n}\n  <\/pre>\n<p><\/code><\/p>\n<p>Yukar\u0131daki kodda <code>@PostConstruct<\/code> metodu Spring uygulamas\u0131 ba\u015flad\u0131\u011f\u0131nda JLibtorrent oturumunu ba\u015flat\u0131rken, <code>@PreDestroy<\/code> metodu uygulama kapan\u0131rken oturumu g\u00fcvenli bir \u015fekilde kapat\u0131r. Ayr\u0131ca, oturuma bir <code>AlertListener<\/code> ekleyerek torrent olaylar\u0131n\u0131 (\u00f6rne\u011fin indirme tamamland\u0131\u011f\u0131nda) dinleyebiliriz. Bu, uygulaman\u0131z\u0131n torrent'lerin durumu hakk\u0131nda bilgi sahibi olmas\u0131n\u0131 sa\u011flar.<\/p>\n<h3>Torrent Ekleyip Durumunu \u0130zleme Mant\u0131\u011f\u0131<\/h3>\n<p>\u015eimdi bir torrent dosyas\u0131n\u0131 oturuma ekleme ve indirme i\u015flemini ba\u015flatma mant\u0131\u011f\u0131n\u0131 olu\u015ftural\u0131m. Bunun i\u00e7in <code>TorrentService<\/code>'imize yeni metodlar ekleyece\u011fiz.<\/p>\n<pre><code>\npackage com.example.javatorrentserver.service;\n\nimport com.frostwire.jlibtorrent.AddTorrentParams;\nimport com.frostwire.jlibtorrent.FileStorage;\nimport com.frostwire.jlibtorrent.Session;\nimport com.frostwire.jlibtorrent.TorrentHandle;\nimport com.frostwire.jlibtorrent.TorrentInfo;\nimport com.frostwire.jlibtorrent.alerts.TorrentAddedAlert;\nimport com.frostwire.jlibtorrent.alerts.TorrentRemovedAlert;\nimport com.frostwire.jlibtorrent.alerts.TorrentStatusAlert;\nimport com.frostwire.jlibtorrent.swig.torrent_status;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Service;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.nio.file.Files;\nimport java.nio.file.Path;\nimport java.nio.file.Paths;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.stream.Collectors;\n\n@Service\npublic class TorrentService {\n\n    \/\/ ... (\u00d6nceki init ve destroy metotlar\u0131 buraya dahil) ...\n    private static final Logger log = LoggerFactory.getLogger(TorrentService.class);\n    private Session session;\n    private final Map<String, TorrentHandle> activeTorrents = new ConcurrentHashMap<>();\n\n    @Value(\"${torrent.download.path:\/tmp\/downloads}\")\n    private String downloadPath;\n\n    \/\/ ... (init ve destroy metotlar\u0131) ...\n\n    \/**\n     * .torrent dosyas\u0131ndan veya magnet linkten torrent ekler.\n     * @param torrentData .torrent dosyas\u0131n\u0131n byte dizisi veya magnet link stringi\n     * @param isMagnetLink true ise torrentData bir magnet linktir\n     * @return Eklenen torrent'in bilgi hash'i (SHA-1)\n     * @throws IOException Torrent dosyas\u0131n\u0131 okurken bir hata olu\u015fursa\n     *\/\n    public String addTorrent(byte[] torrentData, boolean isMagnetLink) throws IOException {\n        AddTorrentParams atp = new AddTorrentParams();\n        Path downloadDir = Paths.get(downloadPath);\n        if (!Files.exists(downloadDir)) {\n            Files.createDirectories(downloadDir);\n        }\n        atp.setSavePath(downloadDir.toAbsolutePath().toString());\n\n        TorrentInfo ti = null;\n        if (isMagnetLink) {\n            atp.setFlags(atp.getFlags().and_(AddTorrentParams.Flags.DOWNLOAD_LIMIT.swig_value())); \/\/ \u0130ndirme limitlerini kald\u0131r\n            atp.setFlags(atp.getFlags().and_(AddTorrentParams.Flags.UPLOAD_LIMIT.swig_value())); \/\/ Y\u00fckleme limitlerini kald\u0131r\n            atp.setFlags(atp.getFlags().and_(AddTorrentParams.Flags.PAUSED.swig_value())); \/\/ Ba\u015flang\u0131\u00e7ta duraklat\u0131lm\u0131\u015f\n            atp.setFlags(atp.getFlags().and_(AddTorrentParams.Flags.AUTO_MANAGED.swig_value())); \/\/ Otomatik y\u00f6netimi etkinle\u015ftir\n            atp.setFlags(atp.getFlags().and_(AddTorrentParams.Flags.SEED_MODE.swig_value())); \/\/ Seed modunu etkinle\u015ftir\n            ti = TorrentInfo.bdecode(torrentData); \/\/ Magnet linkten infohash almak i\u00e7in\n            atp.setTorrentInfo(ti);\n\n            session.addTorrent(atp); \/\/ Magnet linkini do\u011frudan ekle\n        } else {\n            ti = new TorrentInfo(torrentData);\n            atp.setTorrentInfo(ti);\n            session.addTorrent(atp);\n        }\n\n        TorrentHandle th = session.find(ti.infoHash());\n        if (th != null) {\n            th.resume(); \/\/ Ekledikten sonra ba\u015flat\n            activeTorrents.put(ti.infoHash().to  String(), th);\n            log.info(\"Torrent eklendi: {} - Kay\u0131t Yolu: {}\", ti.name(), downloadDir.toAbsolutePath().toString());\n            return ti.infoHash().toString();\n        } else {\n            log.error(\"Torrent eklenemedi: {}\", ti.name());\n            throw new RuntimeException(\"Torrent eklenemedi.\");\n        }\n    }\n\n\n    \/**\n     * Belirtilen torrent'i oturumdan kald\u0131r\u0131r.\n     * @param infoHash Kald\u0131r\u0131lacak torrent'in info hash'i\n     * @param deleteFiles true ise indirilen dosyalar\u0131 da siler\n     *\/\n    public void removeTorrent(String infoHash, boolean deleteFiles) {\n        TorrentHandle th = activeTorrents.get(infoHash);\n        if (th != null) {\n            session.removeTorrent(th, deleteFiles ? Session.DeleteFlags.STORAGE.swig_value() : 0);\n            activeTorrents.remove(infoHash);\n            log.info(\"Torrent kald\u0131r\u0131ld\u0131: {} (Dosyalar silindi: {})\", infoHash, deleteFiles);\n        } else {\n            log.warn(\"Kald\u0131r\u0131lmak istenen torrent bulunamad\u0131: {}\", infoHash);\n        }\n    }\n\n    \/**\n     * T\u00fcm aktif torrentlerin durumunu d\u00f6nd\u00fcr\u00fcr.\n     * @return Aktif torrentlerin listesi\n     *\/\n    public List<TorrentStatus> getAllTorrentStatuses() {\n        return session.getTorrentStatus().stream()\n                .map(TorrentStatus::new)\n                .collect(Collectors.toList());\n    }\n\n    \/**\n     * Belirtilen info hash'e sahip torrent'in durumunu d\u00f6nd\u00fcr\u00fcr.\n     * @param infoHash Sorgulanacak torrent'in info hash'i\n     * @return Torrent durumu veya null\n     *\/\n    public TorrentStatus getTorrentStatus(String infoHash) {\n        TorrentHandle th = activeTorrents.get(infoHash);\n        if (th != null) {\n            torrent_status ts = th.status();\n            return new TorrentStatus(ts);\n        }\n        return null;\n    }\n\n    \/\/ Basit bir TorrentStatus POJO s\u0131n\u0131f\u0131 (JLibtorrent'in kendi TorrentStatus'u ile kar\u0131\u015ft\u0131rmay\u0131n)\n    public static class TorrentStatus {\n        public String infoHash;\n        public String name;\n        public long totalWanted;\n        public long totalDone;\n        public int progress; \/\/ Y\u00fczde olarak\n        public int downloadRate; \/\/ Bayt\/s\n        public int uploadRate; \/\/ Bayt\/s\n        public int numPeers;\n        public String state;\n\n        public TorrentStatus(torrent_status ts) {\n            this.infoHash = ts.getInfoHash().to_string();\n            this.name = ts.getName();\n            this.totalWanted = ts.getTotalWanted();\n            this.totalDone = ts.getTotalDone();\n            this.progress = (int) (ts.getProgress() * 100);\n            this.downloadRate = ts.getDownloadRate();\n            this.uploadRate = ts.getUploadRate();\n            this.numPeers = ts.getNumPeers();\n            this.state = ts.getState().name(); \/\/ State'i string olarak al\n        }\n    }\n}\n  <\/pre>\n<p><\/code><\/p>\n<p>Bu <code>TorrentService<\/code> s\u0131n\u0131f\u0131, torrent ekleme, kald\u0131rma ve durum sorgulama gibi temel i\u015flemleri y\u00fcr\u00fct\u00fcr. <code>downloadPath<\/code> de\u011fi\u015fkeni, indirilen dosyalar\u0131n nereye kaydedilece\u011fini belirler. Ger\u00e7ek d\u00fcnya senaryolar\u0131nda, bu yolun kal\u0131c\u0131 bir depolama alan\u0131na i\u015faret etti\u011finden ve uygun eri\u015fim izinlerine sahip oldu\u011fundan emin olmal\u0131s\u0131n\u0131z. Ayr\u0131ca, <code>TorrentStatus<\/code> ad\u0131nda basit bir POJO olu\u015fturarak, JLibtorrent'in karma\u015f\u0131k <code>torrent_status<\/code> nesnesini daha anla\u015f\u0131l\u0131r bir formata d\u00f6n\u00fc\u015ft\u00fcrd\u00fck. Bu sayede REST API arac\u0131l\u0131\u011f\u0131yla bu bilgiyi d\u0131\u015far\u0131ya sunmak daha kolay olacakt\u0131r.<\/p>\n<h2>Torrent Sunucusu \u0130\u00e7in REST API ve Web Aray\u00fcz\u00fc Nas\u0131l Geli\u015ftirilir?<\/h2>\n<p>\u015eimdiye kadar arka planda \u00e7al\u0131\u015fan bir torrent mant\u0131\u011f\u0131 olu\u015fturduk. Ancak bu mant\u0131\u011f\u0131 d\u0131\u015f d\u00fcnyaya a\u00e7mak ve kullan\u0131c\u0131lar\u0131n etkile\u015fim kurmas\u0131n\u0131 sa\u011flamak i\u00e7in bir REST API ve basit bir web aray\u00fcz\u00fc gereklidir. Spring Boot'un g\u00fcc\u00fc sayesinde, bu ad\u0131m\u0131 olduk\u00e7a h\u0131zl\u0131 bir \u015fekilde tamamlayabiliriz.<\/p>\n<h3>Torrent Y\u00f6netimi \u0130\u00e7in REST Endpointleri<\/h3>\n<p><code>@RestController<\/code> anotasyonunu kullanarak torrent servisimiz i\u00e7in \u00e7e\u015fitli endpoint'ler tan\u0131mlayabiliriz. Bu endpoint'ler, torrent ekleme, torrent listesini alma, torrent silme gibi i\u015flemleri tetikleyecektir.<\/p>\n<pre><code>\npackage com.example.javatorrentserver.controller;\n\nimport com.example.javatorrentserver.service.TorrentService;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.web.bind.annotation.*;\nimport org.springframework.web.multipart.MultipartFile;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.io.IOException;\nimport java.util.List;\n\n@RestController\n@RequestMapping(\"\/api\/torrents\")\npublic class TorrentController {\n\n    private static final Logger log = LoggerFactory.getLogger(TorrentController.class);\n    private final TorrentService torrentService;\n\n    public TorrentController(TorrentService torrentService) {\n        this.torrentService = torrentService;\n    }\n\n    \/**\n     * Yeni bir torrent ekler. .torrent dosyas\u0131 veya magnet link kabul eder.\n     * @param file .torrent dosyas\u0131 (iste\u011fe ba\u011fl\u0131)\n     * @param magnetLink Magnet link stringi (iste\u011fe ba\u011fl\u0131)\n     * @return Eklenen torrent'in info hash'i\n     *\/\n    @PostMapping(\"\/add\")\n    public ResponseEntity<String> addTorrent(@RequestParam(value = \"file\", required = false) MultipartFile file,\n                                          @RequestParam(value = \"magnet\", required = false) String magnetLink) {\n        try {\n            if (file != null && !file.isEmpty()) {\n                String infoHash = torrentService.addTorrent(file.getBytes(), false);\n                return ResponseEntity.ok(\"Torrent eklendi. InfoHash: \" + infoHash);\n            } else if (magnetLink != null && !magnetLink.isEmpty()) {\n                String infoHash = torrentService.addTorrent(magnetLink.getBytes(), true); \/\/ Magnet linki byte olarak i\u015fleriz\n                return ResponseEntity.ok(\"Magnet link eklendi. InfoHash: \" + infoHash);\n            } else {\n                return ResponseEntity.badRequest().body(\"L\u00fctfen bir .torrent dosyas\u0131 veya magnet link sa\u011flay\u0131n.\");\n            }\n        } catch (IOException e) {\n            log.error(\"Torrent eklenirken hata olu\u015ftu: \", e);\n            return ResponseEntity.status(500).body(\"Torrent eklenirken sunucu hatas\u0131.\");\n        } catch (RuntimeException e) {\n            log.error(\"Torrent eklenirken JLibtorrent hatas\u0131: \", e);\n            return ResponseEntity.status(500).body(e.getMessage());\n        }\n    }\n\n    \/**\n     * T\u00fcm aktif torrentlerin listesini ve durumunu d\u00f6nd\u00fcr\u00fcr.\n     * @return Torrent durumlar\u0131 listesi\n     *\/\n    @GetMapping\n    public ResponseEntity<List<TorrentService.TorrentStatus>> getAllTorrents() {\n        List<TorrentService.TorrentStatus> statuses = torrentService.getAllTorrentStatuses();\n        return ResponseEntity.ok(statuses);\n    }\n\n    \/**\n     * Belirli bir torrent'in durumunu d\u00f6nd\u00fcr\u00fcr.\n     * @param infoHash Sorgulanacak torrent'in info hash'i\n     * @return Torrent durumu\n     *\/\n    @GetMapping(\"\/{infoHash}\/status\")\n    public ResponseEntity<TorrentService.TorrentStatus> getTorrentStatus(@PathVariable String infoHash) {\n        TorrentService.TorrentStatus status = torrentService.getTorrentStatus(infoHash);\n        if (status != null) {\n            return ResponseEntity.ok(status);\n        } else {\n            return ResponseEntity.notFound().build();\n        }\n    }\n\n    \/**\n     * Belirtilen torrent'i kald\u0131r\u0131r.\n     * @param infoHash Kald\u0131r\u0131lacak torrent'in info hash'i\n     * @param deleteFiles Torrent dosyalar\u0131n\u0131 diskten de silip silmeyece\u011fi\n     *\/\n    @DeleteMapping(\"\/{infoHash}\")\n    public ResponseEntity<String> removeTorrent(@PathVariable String infoHash,\n                                              @RequestParam(value = \"deleteFiles\", defaultValue = \"false\") boolean deleteFiles) {\n        torrentService.removeTorrent(infoHash, deleteFiles);\n        return ResponseEntity.ok(\"Torrent ba\u015far\u0131yla kald\u0131r\u0131ld\u0131.\");\n    }\n}\n  <\/pre>\n<p><\/code><\/p>\n<p>Bu <code>TorrentController<\/code>, torrent sunucumuzun d\u0131\u015f d\u00fcnyaya a\u00e7\u0131lan kap\u0131s\u0131d\u0131r. Kullan\u0131c\u0131lar (veya di\u011fer servisler) bu API'leri kullanarak torrent ekleyebilir, mevcut torrent'lerin durumunu sorgulayabilir ve hatta torrent'leri sistemden kald\u0131rabilir. <code>@RequestParam<\/code> ve <code>@PathVariable<\/code> gibi Spring anotasyonlar\u0131, HTTP isteklerinden verileri kolayca almam\u0131z\u0131 sa\u011flar.<\/p>\n<h3>Mobil Uyumlu Aray\u00fcz \u0130\u00e7in CSS Yakla\u015f\u0131mlar\u0131<\/h3>\n<p>Modern uygulamalar\u0131n vazge\u00e7ilmez bir par\u00e7as\u0131 olan mobil uyumluluk i\u00e7in, REST API'miz ile ileti\u015fim kuracak basit bir HTML\/JavaScript aray\u00fcz\u00fc d\u00fc\u015f\u00fcnebiliriz. Bu aray\u00fcz\u00fcn farkl\u0131 ekran boyutlar\u0131na uyum sa\u011flamas\u0131 i\u00e7in CSS <code>@media<\/code> sorgular\u0131 kullanmak \u00f6nemlidir. Yukardaki <code>style<\/code> etiketi i\u00e7erisinde baz\u0131 temel mobil uyumlu CSS \u00f6rnekleri bulunmaktad\u0131r. Bunlar\u0131 kullanarak aray\u00fcz\u00fcn\u00fcz\u00fc tasarlayabilirsiniz.<\/p>\n<p>\u00d6rne\u011fin, torrent listesi gibi verileri g\u00f6sterirken, geni\u015f ekranlarda tablo veya kart bazl\u0131 bir d\u00fczen kullanabilirken, mobil cihazlarda her bir torrent'in bilgilerini dikey olarak alt alta s\u0131ralayabilirsiniz. Bu, kullan\u0131c\u0131 deneyimini \u00f6nemli \u00f6l\u00e7\u00fcde iyile\u015ftirir.<\/p>\n<p>Basit bir frontend yap\u0131s\u0131 i\u00e7in, HTML sayfan\u0131zda jQuery veya Vue.js\/React gibi daha geli\u015fmi\u015f bir k\u00fct\u00fcphane kullanarak bu REST API'lerle ileti\u015fim kurabilirsiniz. \u00d6rne\u011fin, t\u00fcm torrentleri listelemek i\u00e7in:<\/p>\n<pre><code>\n<!-- index.html -->\n<!DOCTYPE html>\n<html lang=\"tr\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>Java Torrent Y\u00f6neticisi<\/title>\n    <!-- Stil dosyalar\u0131n\u0131z\u0131 buraya ekleyin -->\n    <link rel=\"stylesheet\" href=\"\/css\/style.css\"> <!-- Kendi CSS dosyan\u0131z -->\n    <style>\n      \/* Yukar\u0131daki style etiketindeki mobil uyumlu CSS kurallar\u0131 buraya ta\u015f\u0131nabilir veya buraya eklenebilir. *\/\n      \/* \u00d6rnek: *\/\n      .torrent-list {\n        display: grid;\n        grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));\n        gap: 20px;\n      }\n      .torrent-item {\n        border: 1px solid #ccc;\n        padding: 15px;\n        border-radius: 8px;\n        background-color: #f9f9f9;\n      }\n      @media (max-width: 768px) {\n        .torrent-list {\n          grid-template-columns: 1fr; \/* Mobil cihazlarda tek s\u00fctun *\/\n        }\n      }\n    <\/style>\n<\/head>\n<body>\n    <div class=\"container\">\n        <h2>Torrent Y\u00f6neticisi<\/h2>\n\n        <div class=\"add-torrent-section\">\n            <h3>Yeni Torrent Ekle<\/h3>\n            <input type=\"file\" id=\"torrentFile\">\n            <button onclick=\"uploadTorrentFile()\">Dosyay\u0131 Y\u00fckle<\/button>\n            <hr>\n            <input type=\"text\" id=\"magnetLinkInput\" placeholder=\"Magnet link yap\u0131\u015ft\u0131r\u0131n\">\n            <button onclick=\"addMagnetLink()\">Magnet Link Ekle<\/button>\n        <\/div>\n\n        <h3>Aktif Torrentler<\/h3>\n        <div id=\"torrentList\" class=\"torrent-list\">\n            <!-- Torrentler buraya y\u00fcklenecek -->\n        <\/div>\n    <\/div>\n\n    <script>\n        function fetchTorrents() {\n            fetch('\/api\/torrents')\n                .then(response => response.json())\n                .then(data => {\n                    const torrentListDiv = document.getElementById('torrentList');\n                    torrentListDiv.innerHTML = ''; \/\/ \u00d6nceki listeyi temizle\n\n                    if (data.length === 0) {\n                        torrentListDiv.innerHTML = '<p>Hen\u00fcz aktif torrent bulunmamaktad\u0131r.<\/p>';\n                        return;\n                    }\n\n                    data.forEach(torrent => {\n                        const itemDiv = document.createElement('div');\n                        itemDiv.className = 'torrent-item';\n                        itemDiv.innerHTML = <code><h4>${torrent.name || &#039;Bilinmeyen Torrent&#039;}<\/h4>\n                            <p><strong>Durum:<\/strong> ${torrent.state}<\/p>\n                            <p><strong>\u0130lerleme:<\/strong> ${torrent.progress}%<\/p>\n                            <p><strong>\u0130ndirme H\u0131z\u0131:<\/strong> ${(torrent.downloadRate \/ 1024).toFixed(2)} KB\/s<\/p>\n                            <p><strong>Y\u00fckleme H\u0131z\u0131:<\/strong> ${(torrent.uploadRate \/ 1024).toFixed(2)} KB\/s<\/p>\n                            <p><strong>Peer Say\u0131s\u0131:<\/strong> ${torrent.numPeers}<\/p>\n                            <button onclick=\"removeTorrent(&#039;${torrent.infoHash}&#039;, false)\">Kald\u0131r (Dosyalar\u0131 Tut)<\/button>\n                            <button onclick=\"removeTorrent(&#039;${torrent.infoHash}&#039;, true)\">Kald\u0131r (Dosyalar\u0131 Sil)<\/button><\/code>;\n                        torrentListDiv.appendChild(itemDiv);\n                    });\n                })\n                .catch(error => console.error('Error fetching torrents:', error));\n        }\n\n        function uploadTorrentFile() {\n            const fileInput = document.getElementById('torrentFile');\n            const file = fileInput.files[0];\n            if (!file) {\n                alert('L\u00fctfen bir .torrent dosyas\u0131 se\u00e7in.');\n                return;\n            }\n\n            const formData = new FormData();\n            formData.append('file', file);\n\n            fetch('\/api\/torrents\/add', {\n                method: 'POST',\n                body: formData\n            })\n            .then(response => response.text())\n            .then(data => {\n                alert(data);\n                fetchTorrents(); \/\/ Listeyi g\u00fcncelle\n            })\n            .catch(error => console.error('Error uploading torrent file:', error));\n        }\n\n        function addMagnetLink() {\n            const magnetLink = document.getElementById('magnetLinkInput').value;\n            if (!magnetLink) {\n                alert('L\u00fctfen bir magnet link girin.');\n                return;\n            }\n\n            const params = new URLSearchParams();\n            params.append('magnet', magnetLink);\n\n            fetch('\/api\/torrents\/add?' + params.toString(), {\n                method: 'POST'\n            })\n            .then(response => response.text())\n            .then(data => {\n                alert(data);\n                fetchTorrents(); \/\/ Listeyi g\u00fcncelle\n            })\n            .catch(error => console.error('Error adding magnet link:', error));\n        }\n\n        function removeTorrent(infoHash, deleteFiles) {\n            fetch(<code>\/api\/torrents\/${infoHash}?deleteFiles=${deleteFiles}<\/code>, {\n                method: 'DELETE'\n            })\n            .then(response => response.text())\n            .then(data => {\n                alert(data);\n                fetchTorrents(); \/\/ Listeyi g\u00fcncelle\n            })\n            .catch(error => console.error('Error removing torrent:', error));\n        }\n\n        \/\/ Sayfa y\u00fcklendi\u011finde torrentleri getir\n        document.addEventListener('DOMContentLoaded', () => {\n            fetchTorrents();\n            \/\/ Belirli aral\u0131klarla listeyi g\u00fcncelle\n            setInterval(fetchTorrents, 5000); \/\/ Her 5 saniyede bir g\u00fcncelle\n        });\n    <\/script>\n<\/body>\n<\/html>\n  <\/pre>\n<p><\/code><\/p>\n<p>Bu HTML\/JS kodu, basit bir aray\u00fcz sa\u011flar ve torrent ekleme, listeleme ve kald\u0131rma i\u015flevlerini g\u00f6sterir. Spring Boot uygulaman\u0131z\u0131n <code>src\/main\/resources\/static<\/code> klas\u00f6r\u00fcne bu dosyay\u0131 koyarak, Spring Boot'un dahili web sunucusu \u00fczerinden eri\u015filebilir hale getirebilirsiniz.<\/p>\n<h2>Geli\u015fmi\u015f Konfig\u00fcrasyonlar, G\u00fcvenlik ve Performans \u0130pu\u00e7lar\u0131 Nelerdir?<\/h2>\n<p>Torrent sunucunuzu canl\u0131 bir ortamda \u00e7al\u0131\u015ft\u0131r\u0131rken dikkate alman\u0131z gereken birka\u00e7 \u00f6nemli nokta bulunmaktad\u0131r: performans optimizasyonu, g\u00fcvenlik ve \u00f6l\u00e7eklenebilirlik. Bu konular, uygulaman\u0131z\u0131n sa\u011flam ve g\u00fcvenilir olmas\u0131n\u0131 sa\u011flar.<\/p>\n<h3>Performans Optimizasyonu<\/h3>\n<ul>\n<li><strong>Disk I\/O Optimizasyonu:<\/strong> Torrent uygulamalar\u0131 yo\u011fun disk I\/O operasyonlar\u0131 gerektirir. Y\u00fcksek h\u0131zl\u0131 SSD'ler kullanmak veya disk \u00f6nbellekleme mekanizmalar\u0131n\u0131 do\u011fru yap\u0131land\u0131rmak performans\u0131 art\u0131rabilir. JLibtorrent'in <code>disk_io_worker_sleep<\/code> gibi ayarlar\u0131n\u0131 inceleyebilirsiniz.<\/li>\n<li><strong>Bellek Y\u00f6netimi:<\/strong> Binlerce torrent'i ayn\u0131 anda y\u00f6netiyorsan\u0131z, JLibtorrent'in ve JVM'in bellek kullan\u0131m\u0131n\u0131 izlemeniz ve optimize etmeniz gerekebilir. <code>session_settings<\/code> i\u00e7erisinde <code>cache_size<\/code> gibi ayarlar bellek kullan\u0131m\u0131n\u0131 etkiler.<\/li>\n<li><strong>A\u011f Ayarlar\u0131:<\/strong> JLibtorrent, TCP ve UDP ba\u011flant\u0131lar\u0131 i\u00e7in bir\u00e7ok a\u011f ayar\u0131 sunar. Ba\u011flant\u0131 limitleri, a\u00e7\u0131k portlar ve bant geni\u015fli\u011fi s\u0131n\u0131rlamalar\u0131 gibi ayarlar, a\u011f trafi\u011fini daha verimli y\u00f6netmenize yard\u0131mc\u0131 olur. \u00d6rne\u011fin, <code>upload_rate_limit<\/code> ve <code>download_rate_limit<\/code> ayarlar\u0131n\u0131 kullanarak global h\u0131z limitleri belirleyebilirsiniz.<\/li>\n<li><strong>DHT ve Peer Say\u0131s\u0131:<\/strong> DHT'yi etkin tutmak peer ke\u015ffi i\u00e7in faydal\u0131d\u0131r. Ancak \u00e7ok y\u00fcksek peer say\u0131s\u0131, a\u011f kaynaklar\u0131n\u0131 t\u00fcketebilir. JLibtorrent, <code>max_peers_per_torrent<\/code> gibi ayarlar sunarak bu durumu y\u00f6netmenize olanak tan\u0131r.<\/li>\n<\/ul>\n<h3>G\u00fcvenlik \u0130pu\u00e7lar\u0131<\/h3>\n<ul>\n<li><strong>Eri\u015fim Kontrol\u00fc:<\/strong> REST API endpoint'lerinizi yetkilendirme (\u00f6rne\u011fin JWT veya OAuth2) ile koruyun. Kimli\u011fi do\u011frulanmam\u0131\u015f kullan\u0131c\u0131lar\u0131n torrent eklemesini veya kald\u0131rmas\u0131n\u0131 engelleyin. Spring Security'yi entegre ederek kolayca g\u00fc\u00e7l\u00fc bir kimlik do\u011frulama ve yetkilendirme katman\u0131 ekleyebilirsiniz.<\/li>\n<li><strong>Girdi Do\u011frulama:<\/strong> Torrent dosyalar\u0131n\u0131 veya magnet linklerini i\u015flerken her zaman girdi do\u011frulama yap\u0131n. K\u00f6t\u00fc niyetli dosyalar veya linkler sisteme zarar verebilir. JLibtorrent \u00e7o\u011fu durumu kendisi halletse de, ekstra katman eklemek her zaman iyidir.<\/li>\n<li><strong>Port G\u00fcvenli\u011fi:<\/strong> JLibtorrent'in kulland\u0131\u011f\u0131 portlar\u0131 (varsay\u0131lan olarak rastgele veya belirli bir aral\u0131k) bir g\u00fcvenlik duvar\u0131 arkas\u0131nda tutun. Sadece gerekli portlara d\u0131\u015far\u0131dan eri\u015fim izni verin.<\/li>\n<li><strong>G\u00fcncelleme Y\u00f6netimi:<\/strong> JLibtorrent ve Spring Boot ba\u011f\u0131ml\u0131l\u0131klar\u0131n\u0131z\u0131 d\u00fczenli olarak g\u00fcncelleyerek bilinen g\u00fcvenlik a\u00e7\u0131klar\u0131ndan korunmaya dikkat edin.<\/li>\n<li><strong>Sandbox Ortam\u0131:<\/strong> M\u00fcmk\u00fcnse, torrent indirmelerini sistemin geri kalan\u0131ndan izole edilmi\u015f (\u00f6rne\u011fin Docker konteyneri i\u00e7inde) bir sandbox ortam\u0131nda ger\u00e7ekle\u015ftirin. Bu, k\u00f6t\u00fc niyetli i\u00e7eriklerin ana sisteme bula\u015fma riskini azalt\u0131r.<\/li>\n<\/ul>\n<div class=\"expert-tip\">\n    Uzman \u0130pucu: Torrent sunucunuzu Dockerize etmek, hem ba\u011f\u0131ml\u0131l\u0131k y\u00f6netimini basitle\u015ftirir hem de farkl\u0131 ortamlar aras\u0131nda ta\u015f\u0131nabilirli\u011fi art\u0131r\u0131r. Ayr\u0131ca, Docker'\u0131n kaynak k\u0131s\u0131tlama \u00f6zellikleri sayesinde sunucunuzun di\u011fer uygulamalar\u0131 etkilemesini \u00f6nleyebilirsiniz.\n  <\/div>\n<h3>Ger\u00e7ek D\u00fcnya Senaryosu: \u0130\u00e7erik Da\u011f\u0131t\u0131m A\u011f\u0131 (CDN) i\u00e7in Kullan\u0131m<\/h3>\n<p>B\u00fcy\u00fck medya \u015firketleri veya yaz\u0131l\u0131m geli\u015ftiriciler, s\u0131k\u00e7a g\u00fcncellenen b\u00fcy\u00fck dosyalar\u0131 (oyun yamalar\u0131, HD video i\u00e7erikleri, i\u015fletim sistemi ISO'lar\u0131) t\u00fcm d\u00fcnyaya da\u011f\u0131tmak zorundad\u0131r. Geleneksel CDN'ler bu konuda yard\u0131mc\u0131 olsa da, bant geni\u015fli\u011fi maliyetleri ve belirli b\u00f6lgelerdeki yava\u015f eri\u015fim sorunlar\u0131 yaratabilir. Kendi Spring Boot ve JLibtorrent tabanl\u0131 sunucular\u0131n\u0131 kullanarak hibrit bir CDN \u00e7\u00f6z\u00fcm\u00fc olu\u015fturabilirler. \u00d6rne\u011fin:<\/p>\n<ul>\n<li>\u015eirket, ana sunucular\u0131nda bir veya daha fazla Spring Boot torrent sunucusu \u00e7al\u0131\u015ft\u0131r\u0131r ve yeni i\u00e7erikleri ilk seeder olarak bu sunuculara ekler.<\/li>\n<li>Uzak b\u00f6lgelerdeki da\u011f\u0131t\u0131m noktalar\u0131 veya m\u00fc\u015fteriler, bu i\u00e7erikleri bir web aray\u00fcz\u00fc veya API arac\u0131l\u0131\u011f\u0131yla kendi istemcilerine (veya mini-sunucular\u0131na) \u00e7eker.<\/li>\n<li>\u0130\u00e7erik \u00e7ekildik\u00e7e, her bir istemci ayn\u0131 zamanda bir seeder g\u00f6revi g\u00f6rerek a\u011f \u00fczerindeki y\u00fck\u00fc hafifletir. Bu, \u00f6zellikle talebin y\u00fcksek oldu\u011fu anlarda bant geni\u015fli\u011fi \u00fczerindeki bask\u0131y\u0131 azalt\u0131r ve indirme h\u0131zlar\u0131n\u0131 art\u0131r\u0131r.<\/li>\n<\/ul>\n<p>Bu yakla\u015f\u0131m, maliyetleri d\u00fc\u015f\u00fcrmenin yan\u0131 s\u0131ra, a\u011f\u0131n da\u011f\u0131t\u0131k yap\u0131s\u0131 sayesinde tek bir hata noktas\u0131n\u0131n ortadan kalkmas\u0131n\u0131 ve daha resilient (dayan\u0131kl\u0131) bir da\u011f\u0131t\u0131m sistemine sahip olman\u0131z\u0131 sa\u011flar. Ayr\u0131ca, JLibtorrent'in g\u00fc\u00e7l\u00fc API'leri sayesinde, hangi i\u00e7eri\u011fin ne kadar indirildi\u011fini, kimlerin indirdi\u011fini ve ne kadar y\u00fckleme yap\u0131ld\u0131\u011f\u0131n\u0131 detayl\u0131 bir \u015fekilde izleyebilir ve raporlayabilirsiniz.<\/p>\n<h2>Sonu\u00e7 ve S\u0131k\u00e7a Sorulan Sorular<\/h2>\n<p>Bu makalede, Spring Boot ve JLibtorrent kullanarak nas\u0131l g\u00fc\u00e7l\u00fc bir Java torrent sunucusu olu\u015fturaca\u011f\u0131n\u0131z\u0131 ad\u0131m ad\u0131m inceledik. Torrent protokol\u00fcn\u00fcn temel \u00e7al\u0131\u015fma prensiplerinden JLibtorrent'in entegrasyonuna, Spring Boot ile REST API geli\u015ftirmekten mobil uyumlu aray\u00fcze kadar geni\u015f bir yelpazeyi kapsayan bilgiler sunduk. Kendi torrent sunucunuzu kurmak, sadece teknik bir ba\u015far\u0131 de\u011fil, ayn\u0131 zamanda b\u00fcy\u00fck \u00f6l\u00e7ekli dosya da\u011f\u0131t\u0131m\u0131nda size e\u015fsiz bir kontrol ve esneklik sa\u011flayan stratejik bir avantajd\u0131r. Gerek ki\u015fisel kullan\u0131m i\u00e7in bir medya sunucusu, gerekse kurumsal ihtiya\u00e7lar i\u00e7in bir i\u00e7erik da\u011f\u0131t\u0131m platformu olsun, bu bilgilerle sa\u011flam bir temel olu\u015fturabilirsiniz. Unutmay\u0131n ki, canl\u0131 ortamlarda g\u00fcvenlik ve performans optimizasyonlar\u0131 her zaman \u00f6ncelikli olmal\u0131d\u0131r.<\/p>\n<h3>S\u0131k\u00e7a Sorulan Sorular<\/h3>\n<p><strong>1. JLibtorrent sadece indirme i\u00e7in mi kullan\u0131l\u0131r, yoksa dosya payla\u015f\u0131m\u0131 (seeding) da yapabilir miyim?<\/strong><br \/>\n  Evet, JLibtorrent tam te\u015fekk\u00fcll\u00fc bir torrent k\u00fct\u00fcphanesidir ve hem indirme (leeching) hem de dosya payla\u015f\u0131m\u0131 (seeding) yapabilir. \u0130ndirdi\u011finiz bir torrent tamamland\u0131\u011f\u0131nda, otomatik olarak seeder moduna ge\u00e7erek di\u011fer peer'lara dosya par\u00e7alar\u0131n\u0131 y\u00fcklemeye devam edecektir. Bu, P2P a\u011f\u0131n\u0131n temel \u00e7al\u0131\u015fma prensibidir.<\/p>\n<p><strong>2. Olu\u015fturdu\u011fum torrent sunucusunu Docker ile nas\u0131l da\u011f\u0131t\u0131r\u0131m?<\/strong><br \/>\n  Spring Boot uygulaman\u0131z\u0131 bir JAR dosyas\u0131 olarak paketledikten sonra, temel bir Java Runtime Environment (JRE) imaj\u0131 \u00fczerine kendi Docker imaj\u0131n\u0131z\u0131 olu\u015fturabilirsiniz. <code>Dockerfile<\/code> i\u00e7inde JAR dosyan\u0131z\u0131 kopyalar, JLibtorrent i\u00e7in gerekli native k\u00fct\u00fcphaneleri (genellikle JLibtorrent ba\u011f\u0131ml\u0131l\u0131\u011f\u0131 ile birlikte gelir) ayarlars\u0131n\u0131z ve uygulaman\u0131z\u0131 ba\u015flat\u0131rs\u0131n\u0131z. Portlar\u0131 (\u00f6rne\u011fin 8080 Spring Boot i\u00e7in, torrent i\u00e7in JLibtorrent'in kulland\u0131\u011f\u0131 portlar) d\u0131\u015far\u0131ya map etmeyi unutmay\u0131n.<\/p>\n<p><strong>3. Torrent sunucumun g\u00fcvenlik duvar\u0131 ayarlar\u0131 nas\u0131l olmal\u0131?<\/strong><br \/>\n  JLibtorrent'in peer'larla ileti\u015fim kurabilmesi i\u00e7in belirli portlar\u0131n d\u0131\u015far\u0131ya a\u00e7\u0131k olmas\u0131 gerekir. Genellikle TCP ve UDP i\u00e7in rastgele portlar kullan\u0131r. E\u011fer UPnP veya NAT-PMP etkinse, router'\u0131n\u0131z bu portlar\u0131 otomatik olarak a\u00e7maya \u00e7al\u0131\u015facakt\u0131r. Aksi takdirde, sunucunuzun g\u00fcvenlik duvar\u0131nda ve router'\u0131n\u0131zda manuel port y\u00f6nlendirme (port forwarding) yapman\u0131z gerekebilir. Sadece JLibtorrent'in kulland\u0131\u011f\u0131 portlar\u0131 ve Spring Boot API'nizin dinledi\u011fi portu (varsay\u0131lan 8080) a\u00e7maya \u00f6zen g\u00f6sterin.<\/p>\n<p><strong>4. B\u00fcy\u00fck dosyalar i\u00e7in JLibtorrent performans\u0131 nas\u0131ld\u0131r?<\/strong><br \/>\n  JLibtorrent, C++ tabanl\u0131 libtorrent-rasterbar k\u00fct\u00fcphanesinin Java ba\u011flay\u0131c\u0131s\u0131 oldu\u011fundan, y\u00fcksek performansl\u0131 ve optimize edilmi\u015f bir k\u00fct\u00fcphanedir. B\u00fcy\u00fck dosyalar ve y\u00fcksek e\u015f say\u0131s\u0131 ile \u00e7al\u0131\u015f\u0131rken bile olduk\u00e7a verimlidir. Ancak, sisteminizin disk I\/O h\u0131z\u0131, a\u011f bant geni\u015fli\u011fi ve CPU kaynaklar\u0131 genel performans\u0131 do\u011frudan etkileyecektir. Optimizasyon ipu\u00e7lar\u0131n\u0131 takip etmek, performans\u0131 maksimize etmenize yard\u0131mc\u0131 olacakt\u0131r.<\/p>\n<p><strong>5. Torrent dosyalar\u0131n\u0131 otomatik olarak izleyip ekleyebilir miyim?<\/strong><br \/>\n  Evet, Spring Boot uygulaman\u0131zda bir <code>@Scheduled<\/code> g\u00f6rev veya bir <code>FileSystemWatcher<\/code> kullanarak belirli bir klas\u00f6r\u00fc izleyebilir ve bu klas\u00f6re yeni bir <code>.torrent<\/code> dosyas\u0131 eklendi\u011finde otomatik olarak <code>TorrentService<\/code> \u00fczerinden oturuma ekleyebilirsiniz. Bu, bir otomasyon senaryosu i\u00e7in olduk\u00e7a faydal\u0131 bir \u00f6zelliktir.<\/p>\n<\/div>\n<p><\/body><\/p>\n","protected":false},"excerpt":{"rendered":"P2P (Peer-to-Peer) dosya payla\u015f\u0131m\u0131 d\u00fcnyas\u0131nda kendi sunucunuzu kurarak veri aktar\u0131m\u0131n\u0131 kontrol etmek ister miydiniz? \u00d6zellikle b\u00fcy\u00fck veri setlerinin&hellip;","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"csco_page_header_type":"","csco_page_load_nextpost":"","csco_page_subscribe_form":"","csco_page_contact_form":"","footnotes":""},"categories":[1408],"tags":[],"class_list":{"0":"post-30921","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-java","7":"cs-entry","8":"cs-video-wrap"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.5 (Yoast SEO v25.3.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Spring Boot ve JLibtorrent ile Java Torrent Sunucusu Nas\u0131l Yap\u0131l\u0131r?<\/title>\n<meta name=\"description\" content=\"P2P (Peer-to-Peer) dosya payla\u015f\u0131m\u0131 d\u00fcnyas\u0131nda kendi sunucunuzu kurarak veri aktar\u0131m\u0131n\u0131 kontrol etmek ister miydiniz? \u00d6zellikle b\u00fcy\u00fck veri setlerinin da\u011f\u0131t\u0131m\u0131nda veya ki\u015fisel bulut \u00e7\u00f6z\u00fcmlerinde, Java&#039;n\u0131n g\u00fcc\u00fcn\u00fc Spring Boot&#039;un esnekli\u011fi ve JLibtorrent&#039;in yetenekleriyle birle\u015ftirerek \u00f6zel bir torrent sunucusu olu\u015fturabilirsiniz. Bu kapsaml\u0131 rehberde, s\u0131f\u0131rdan ad\u0131m ad\u0131m kendi Java torrent sunucunuzu nas\u0131l in\u015fa edece\u011finizi \u00f6\u011frenecek, teorik bilgilerden pratik kod \u00f6rneklerine kadar her detay\u0131 ke\u015ffedeceksiniz.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fatihsoysal.com\/blog\/spring-boot-ve-jlibtorrent-ile-java-torrent-sunucusu-nasil-yapilir\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Spring Boot ve JLibtorrent ile Java Torrent Sunucusu Nas\u0131l Yap\u0131l\u0131r?\" \/>\n<meta property=\"og:description\" content=\"P2P (Peer-to-Peer) dosya payla\u015f\u0131m\u0131 d\u00fcnyas\u0131nda kendi sunucunuzu kurarak veri aktar\u0131m\u0131n\u0131 kontrol etmek ister miydiniz? \u00d6zellikle b\u00fcy\u00fck veri setlerinin da\u011f\u0131t\u0131m\u0131nda veya ki\u015fisel bulut \u00e7\u00f6z\u00fcmlerinde, Java&#039;n\u0131n g\u00fcc\u00fcn\u00fc Spring Boot&#039;un esnekli\u011fi ve JLibtorrent&#039;in yetenekleriyle birle\u015ftirerek \u00f6zel bir torrent sunucusu olu\u015fturabilirsiniz. Bu kapsaml\u0131 rehberde, s\u0131f\u0131rdan ad\u0131m ad\u0131m kendi Java torrent sunucunuzu nas\u0131l in\u015fa edece\u011finizi \u00f6\u011frenecek, teorik bilgilerden pratik kod \u00f6rneklerine kadar her detay\u0131 ke\u015ffedeceksiniz.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fatihsoysal.com\/blog\/spring-boot-ve-jlibtorrent-ile-java-torrent-sunucusu-nasil-yapilir\/\" \/>\n<meta property=\"og:site_name\" content=\"Kodlar\u0131n Gizemli D\u00fcnyas\u0131\" \/>\n<meta property=\"article:published_time\" content=\"2025-10-03T09:31:55+00:00\" \/>\n<meta name=\"author\" content=\"Fatih Soysal\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"Fatih Soysal\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/spring-boot-ve-jlibtorrent-ile-java-torrent-sunucusu-nasil-yapilir\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/spring-boot-ve-jlibtorrent-ile-java-torrent-sunucusu-nasil-yapilir\/\"},\"author\":{\"name\":\"Fatih Soysal\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"headline\":\"Spring Boot ve JLibtorrent ile Java Torrent Sunucusu Nas\u0131l Yap\u0131l\u0131r?\",\"datePublished\":\"2025-10-03T09:31:55+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/spring-boot-ve-jlibtorrent-ile-java-torrent-sunucusu-nasil-yapilir\/\"},\"wordCount\":3073,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"articleSection\":[\"Java\"],\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/spring-boot-ve-jlibtorrent-ile-java-torrent-sunucusu-nasil-yapilir\/#respond\"]}],\"copyrightYear\":\"2025\",\"copyrightHolder\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/spring-boot-ve-jlibtorrent-ile-java-torrent-sunucusu-nasil-yapilir\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/spring-boot-ve-jlibtorrent-ile-java-torrent-sunucusu-nasil-yapilir\/\",\"name\":\"Spring Boot ve JLibtorrent ile Java Torrent Sunucusu Nas\u0131l Yap\u0131l\u0131r?\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\"},\"datePublished\":\"2025-10-03T09:31:55+00:00\",\"description\":\"P2P (Peer-to-Peer) dosya payla\u015f\u0131m\u0131 d\u00fcnyas\u0131nda kendi sunucunuzu kurarak veri aktar\u0131m\u0131n\u0131 kontrol etmek ister miydiniz? \u00d6zellikle b\u00fcy\u00fck veri setlerinin da\u011f\u0131t\u0131m\u0131nda veya ki\u015fisel bulut \u00e7\u00f6z\u00fcmlerinde, Java'n\u0131n g\u00fcc\u00fcn\u00fc Spring Boot'un esnekli\u011fi ve JLibtorrent'in yetenekleriyle birle\u015ftirerek \u00f6zel bir torrent sunucusu olu\u015fturabilirsiniz. Bu kapsaml\u0131 rehberde, s\u0131f\u0131rdan ad\u0131m ad\u0131m kendi Java torrent sunucunuzu nas\u0131l in\u015fa edece\u011finizi \u00f6\u011frenecek, teorik bilgilerden pratik kod \u00f6rneklerine kadar her detay\u0131 ke\u015ffedeceksiniz.\",\"breadcrumb\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/spring-boot-ve-jlibtorrent-ile-java-torrent-sunucusu-nasil-yapilir\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/spring-boot-ve-jlibtorrent-ile-java-torrent-sunucusu-nasil-yapilir\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/spring-boot-ve-jlibtorrent-ile-java-torrent-sunucusu-nasil-yapilir\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Anasayfa\",\"item\":\"https:\/\/fatihsoysal.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Spring Boot ve JLibtorrent ile Java Torrent Sunucusu Nas\u0131l Yap\u0131l\u0131r?\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/\",\"name\":\"Fatihsoysal.com\",\"description\":\"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim\",\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\",\"name\":\"Fatih Soysal\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"contentUrl\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"width\":512,\"height\":512,\"caption\":\"Fatih Soysal\"},\"logo\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\"},\"description\":\"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Spring Boot ve JLibtorrent ile Java Torrent Sunucusu Nas\u0131l Yap\u0131l\u0131r?","description":"P2P (Peer-to-Peer) dosya payla\u015f\u0131m\u0131 d\u00fcnyas\u0131nda kendi sunucunuzu kurarak veri aktar\u0131m\u0131n\u0131 kontrol etmek ister miydiniz? \u00d6zellikle b\u00fcy\u00fck veri setlerinin da\u011f\u0131t\u0131m\u0131nda veya ki\u015fisel bulut \u00e7\u00f6z\u00fcmlerinde, Java'n\u0131n g\u00fcc\u00fcn\u00fc Spring Boot'un esnekli\u011fi ve JLibtorrent'in yetenekleriyle birle\u015ftirerek \u00f6zel bir torrent sunucusu olu\u015fturabilirsiniz. Bu kapsaml\u0131 rehberde, s\u0131f\u0131rdan ad\u0131m ad\u0131m kendi Java torrent sunucunuzu nas\u0131l in\u015fa edece\u011finizi \u00f6\u011frenecek, teorik bilgilerden pratik kod \u00f6rneklerine kadar her detay\u0131 ke\u015ffedeceksiniz.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/fatihsoysal.com\/blog\/spring-boot-ve-jlibtorrent-ile-java-torrent-sunucusu-nasil-yapilir\/","og_locale":"tr_TR","og_type":"article","og_title":"Spring Boot ve JLibtorrent ile Java Torrent Sunucusu Nas\u0131l Yap\u0131l\u0131r?","og_description":"P2P (Peer-to-Peer) dosya payla\u015f\u0131m\u0131 d\u00fcnyas\u0131nda kendi sunucunuzu kurarak veri aktar\u0131m\u0131n\u0131 kontrol etmek ister miydiniz? \u00d6zellikle b\u00fcy\u00fck veri setlerinin da\u011f\u0131t\u0131m\u0131nda veya ki\u015fisel bulut \u00e7\u00f6z\u00fcmlerinde, Java'n\u0131n g\u00fcc\u00fcn\u00fc Spring Boot'un esnekli\u011fi ve JLibtorrent'in yetenekleriyle birle\u015ftirerek \u00f6zel bir torrent sunucusu olu\u015fturabilirsiniz. Bu kapsaml\u0131 rehberde, s\u0131f\u0131rdan ad\u0131m ad\u0131m kendi Java torrent sunucunuzu nas\u0131l in\u015fa edece\u011finizi \u00f6\u011frenecek, teorik bilgilerden pratik kod \u00f6rneklerine kadar her detay\u0131 ke\u015ffedeceksiniz.","og_url":"https:\/\/fatihsoysal.com\/blog\/spring-boot-ve-jlibtorrent-ile-java-torrent-sunucusu-nasil-yapilir\/","og_site_name":"Kodlar\u0131n Gizemli D\u00fcnyas\u0131","article_published_time":"2025-10-03T09:31:55+00:00","author":"Fatih Soysal","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"Fatih Soysal","Tahmini okuma s\u00fcresi":"6 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/fatihsoysal.com\/blog\/spring-boot-ve-jlibtorrent-ile-java-torrent-sunucusu-nasil-yapilir\/#article","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/spring-boot-ve-jlibtorrent-ile-java-torrent-sunucusu-nasil-yapilir\/"},"author":{"name":"Fatih Soysal","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"headline":"Spring Boot ve JLibtorrent ile Java Torrent Sunucusu Nas\u0131l Yap\u0131l\u0131r?","datePublished":"2025-10-03T09:31:55+00:00","mainEntityOfPage":{"@id":"https:\/\/fatihsoysal.com\/blog\/spring-boot-ve-jlibtorrent-ile-java-torrent-sunucusu-nasil-yapilir\/"},"wordCount":3073,"commentCount":0,"publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"articleSection":["Java"],"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/fatihsoysal.com\/blog\/spring-boot-ve-jlibtorrent-ile-java-torrent-sunucusu-nasil-yapilir\/#respond"]}],"copyrightYear":"2025","copyrightHolder":{"@id":"https:\/\/fatihsoysal.com\/blog\/#organization"}},{"@type":"WebPage","@id":"https:\/\/fatihsoysal.com\/blog\/spring-boot-ve-jlibtorrent-ile-java-torrent-sunucusu-nasil-yapilir\/","url":"https:\/\/fatihsoysal.com\/blog\/spring-boot-ve-jlibtorrent-ile-java-torrent-sunucusu-nasil-yapilir\/","name":"Spring Boot ve JLibtorrent ile Java Torrent Sunucusu Nas\u0131l Yap\u0131l\u0131r?","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/#website"},"datePublished":"2025-10-03T09:31:55+00:00","description":"P2P (Peer-to-Peer) dosya payla\u015f\u0131m\u0131 d\u00fcnyas\u0131nda kendi sunucunuzu kurarak veri aktar\u0131m\u0131n\u0131 kontrol etmek ister miydiniz? \u00d6zellikle b\u00fcy\u00fck veri setlerinin da\u011f\u0131t\u0131m\u0131nda veya ki\u015fisel bulut \u00e7\u00f6z\u00fcmlerinde, Java'n\u0131n g\u00fcc\u00fcn\u00fc Spring Boot'un esnekli\u011fi ve JLibtorrent'in yetenekleriyle birle\u015ftirerek \u00f6zel bir torrent sunucusu olu\u015fturabilirsiniz. Bu kapsaml\u0131 rehberde, s\u0131f\u0131rdan ad\u0131m ad\u0131m kendi Java torrent sunucunuzu nas\u0131l in\u015fa edece\u011finizi \u00f6\u011frenecek, teorik bilgilerden pratik kod \u00f6rneklerine kadar her detay\u0131 ke\u015ffedeceksiniz.","breadcrumb":{"@id":"https:\/\/fatihsoysal.com\/blog\/spring-boot-ve-jlibtorrent-ile-java-torrent-sunucusu-nasil-yapilir\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fatihsoysal.com\/blog\/spring-boot-ve-jlibtorrent-ile-java-torrent-sunucusu-nasil-yapilir\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/fatihsoysal.com\/blog\/spring-boot-ve-jlibtorrent-ile-java-torrent-sunucusu-nasil-yapilir\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Anasayfa","item":"https:\/\/fatihsoysal.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Spring Boot ve JLibtorrent ile Java Torrent Sunucusu Nas\u0131l Yap\u0131l\u0131r?"}]},{"@type":"WebSite","@id":"https:\/\/fatihsoysal.com\/blog\/#website","url":"https:\/\/fatihsoysal.com\/blog\/","name":"Fatihsoysal.com","description":"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim","publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1","name":"Fatih Soysal","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","contentUrl":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","width":512,"height":512,"caption":"Fatih Soysal"},"logo":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/"},"description":"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.","url":"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/"}]}},"yoast_meta":{"yoast_wpseo_title":"","yoast_wpseo_metadesc":"","yoast_wpseo_canonical":""},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/30921","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/comments?post=30921"}],"version-history":[{"count":0,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/30921\/revisions"}],"wp:attachment":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/media?parent=30921"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/categories?post=30921"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/tags?post=30921"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}