alanmcgovern / monotorrent

The official repository for MonoTorrent, a bittorrent library for .NET
https://github.com/alanmcgovern/monotorrent
MIT License
1.15k stars 397 forks source link

Peers not updating / displaying #550

Closed rjclarkewp007 closed 2 years ago

rjclarkewp007 commented 2 years ago

Hi, thanks for all the hard work for this project! I just moved from another project (BitSwarm) to MonoTorrent and damn this is so much better!

Anyway, I am a complete noob with no coding experience, but I used Google and Youtube to teach myself some coding skills and thus far I have been able to create a cool a little game launcher where players can download a game using my launcher (making use of MonoTorrent), extract the zip file and then play the game from the launcher.

I am using VS2022 (coding in C# .NetFramework 4.8 windows forms).

I have 3 questions which I hope someone can help me with while explaining it to me like I am a baby :)

  1. When new peers are available they don't show in my peers label (peer label does not update in other words), but I can see the download rate increases)

    peers.Text = "Peers: " + manager.Peers.Seeds.ToString() + "/" + manager.Peers.Available.ToString();
  2. Available peers jumps to 5 or 7 and then down to 0 and it stays there for entire download. I have 3 peers available. image

  3. Does not download from other seeders (for example qbittorrent) until that seeder/client is at 100% completed. Well this works sort off, I paused the download in my application and then started again after about 15min and then it actually started to download from the incomplete seeder as well, but the peers did not update from 2 to 3. Just stays on 2 / 0 as per image above.

My coding (Probably not how it should be haha):

public async void downloader()
{
                // Give an example of how settings can be modified for the engine.
                var settingBuilder = new EngineSettingsBuilder
                {
                    AllowPortForwarding = true,
                    AutoSaveLoadDhtCache = true,
                    AutoSaveLoadFastResume = true,
                    AutoSaveLoadMagnetLinkMetadata = true,
                    AllowLocalPeerDiscovery = true,
                    ListenPort = 15551,
                    MaximumConnections = 300,
                    DhtPort = 0,

                };

                dhtEngine = new DhtEngine(new IPEndPoint(IPAddress.Any, 0));
                var torrent = await Torrent.LoadAsync(torrentfile);
                TorrentEngine = new ClientEngine(settingBuilder.ToSettings());
                manager = await TorrentEngine.AddAsync(torrent, installdir);
                manager.TorrentStateChanged += Manager_TorrentStateChanged;
                var peers = await manager.GetPeersAsync();

                await dhtEngine.StartAsync();
                await manager.StartAsync();
}
private void Manager_TorrentStateChanged(object sender, TorrentStateChangedEventArgs e)
        {
            while (manager.State == TorrentState.Downloading)
            {
                manager.LocalPeerAnnounceAsync();
                manager.DhtAnnounceAsync();
                labelspeed.Text = "Download: " + ConvertBytesToMegabytes(manager.Monitor.DownloadSpeed).ToString("0.00") + " MB/s";
                label_uploadSpeed.Text = "Upload: " + ConvertBytesToMegabytes(manager.Monitor.UploadSpeed).ToString("0.00" + " MB/s");
                peers.Text = "Peers: " + manager.Peers.Seeds.ToString() + "/" + manager.Peers.Available.ToString();
                progressBar1.Value = (int)Double.Parse(manager.Progress.ToString());
                label1.Text = "Downloading... " + ConvertBytesToGigabytes(manager.Monitor.DataBytesDownloaded).ToString("0.00") + "/" + ConvertBytesToGigabytes(manager.Size).ToString("0.00") + "GB";                

                // Calculate ETA
                var EtaInSeconds = Math.Min(MaxETA, (int)((manager.Torrent.Size - manager.Monitor.DataBytesDownloaded) / (double)Math.Max(1, manager.Monitor.DownloadSpeed)));
                TimeSpan time = TimeSpan.FromSeconds(EtaInSeconds);
                string str = time.ToString(@"hh\:mm\:ss");
                eta.Text = "ETA: " + str.ToString();
            }

            if (manager.State == TorrentState.Paused)
            {
                label1.Text = "Download Paused";
            }

            if (manager.State == TorrentState.Stopped)
            {
                label1.Text = "Download Stopped.";
            }

            if (manager.Complete)
            {
                ExtractFile();
            }
        }
alanmcgovern commented 2 years ago

Hrmm, the third point in particular doesn't sound normal/correct. The library should download from anyone equally. Could you share some code, or the torrent Sha, so I can investigate further? By any chance do you know if this is a BitTorrent v1, V2 or hybrid (v1 and v2) torrent? Also, which version of MonoTorrent are you using?

For cases where you're updating your UI, you might need to explicitly enqueue this work on the main UI thread prior to performing any updates. This might help.

I'll double check that the peer count values are correct, though (from memory) those values are straight from the internal List which tracks connected peers. Huh.

rjclarkewp007 commented 2 years ago

Hey there, sorry for late reply.

I checked and the torrent is hybrid. I am using the latest version of MonoTorrent. Not too sure what you mean by "explicitly enqueue this work on the main UI thread prior to performing any updates"..

Is there a specific past of the code you would like to see? basically the parts I copied in original thread is the ones i use to start the download using a new thread like this:

private Thread downloadthread;
        private void downloadThreadStart()
        {
            downloadthread = new Thread(Updater);
            downloadthread.IsBackground = true;
            downloadthread.Start();
        }
    public async void Updater() //Thread to make downloader run
    {
        MethodInvoker StartingDownload = delegate
        {
            try
            {
                label1.Text = "Checking files..please wait...";
                stop_button.Visible = true;
                peers.Visible = true;
                eta.Visible = true;
                resume.Enabled = false;
                resume.Visible = false;
                pause.Enabled = true;
                pause.Visible = true;

            }
            catch (Exception)
            {

            }
        };

        MethodInvoker errorDownloading = delegate
        {
            try
            {
                stop_button.Visible = false;

            }
            catch (Exception)
            {

            }
        };

        Directory.SetCurrentDirectory(launcherdir);
        string installdir = File.ReadLines("config.ini").Skip(10).Take(1).First();
        Directory.SetCurrentDirectory(installdir);

        //Download torrent file first
        startTorrentFileDownload();

        //Download Current game version 7zip file using MonoTorrent.

        try
        {
            // Give an example of how settings can be modified for the engine.
            var settingBuilder = new EngineSettingsBuilder
            {
                // Allow the engine to automatically forward ports using upnp/nat-pmp (if a compatible router is available)
                AllowPortForwarding = true,

                // Automatically save a cache of the DHT table when all torrents are stopped.
                AutoSaveLoadDhtCache = true,

                // Automatically save 'FastResume' data when TorrentManager.StopAsync is invoked, automatically load it
                // before hash checking the torrent. Fast Resume data will be loaded as part of 'engine.AddAsync' if
                // torrent metadata is available. Otherwise, if a magnetlink is used to download a torrent, fast resume
                // data will be loaded after the metadata has been downloaded. 
                AutoSaveLoadFastResume = true,

                // If a MagnetLink is used to download a torrent, the engine will try to load a copy of the metadata
                // it's cache directory. Otherwise the metadata will be downloaded and stored in the cache directory
                // so it can be reloaded later.
                AutoSaveLoadMagnetLinkMetadata = true,

                AllowLocalPeerDiscovery = true,

                MaximumConnections = 300,

            };

            var torrent = await Torrent.LoadAsync(torrentfile);
            dhtEngine = new DhtEngine(new IPEndPoint(IPAddress.Any, 0));               
            TorrentEngine = new ClientEngine(settingBuilder.ToSettings());
            manager = await TorrentEngine.AddAsync(torrent, installdir);
            manager.TorrentStateChanged += Manager_TorrentStateChanged;
            manager.PeersFound += Manager_PeersFound;

            label1.Invoke(StartingDownload);

            await dhtEngine.StartAsync();
            await manager.StartAsync();
            Directory.SetCurrentDirectory(launcherdir);

        }
        catch (Exception e1)
        {
            MessageBox.Show(e1.Message + "\r\n" + e1.StackTrace);
            label1.Invoke(errorDownloading);
            MessageBox.Show("Previous session data has been removed. Please restart.");
            Directory.SetCurrentDirectory(launcherdir);
            Application.Exit();
        }

    }
alanmcgovern commented 2 years ago

Ah, I just realised what the issue is for '1'. You're not counting 'leechers'. Also, you should use total rather than `available.

Out of curiosity, are the intellisense code completion hints showing up for you?

peers.Text = "Peers: " + manager.Peers.Seeds.ToString() + "/" + manager.Peers.Available.ToString();
peers.Text = "Peers: " + (manager.Peers.Leeches + manager.Peers.Seeds).ToString() + "/" + manager.Peers.Total.ToString();

i'll check the rest later :)

rjclarkewp007 commented 2 years ago

Hey, so there doesn't seem to be an option for Total.

As for the rest, i am now counting the leeches and seeds. Will see how that shows up. If I use Available instead of Total i still see 0. image

I don't really see any hints ever showing up, except when i do += parts..

rjclarkewp007 commented 2 years ago

Hey, so I think this has been resolved. After using manager.Peers.Leechs + manager.Peers.Seeds the peers seems to be showing up correctly now.

Also tested a bit more and downloads seems to be working even if the other client is not at 100% yet.

Available peers still seem to be an issue, but i just removed that part for now.

Thanks for the help!