Actualité Tutoriels Liens contact dotnet-tech.com - Home - Tutoriels techniques avec code source Dotnet-tech.com : Les site sur les technologies .Net

 

 

BITS : Le service de transfert intelligent de Windows

 

 

24 Avril 2007

Par Elise Dupont

 

 

Version PDF à télécharger

 

 

Droit de diffusion:
L'ensemble ou partie de ce document ainsi que le code mis à disposition, ne peut être diffusé sur d'autres sites Web sans l'autorisation au préalable de son créateur.

 

 

Avant Propos :

Lors d’un projet récent, j’avais besoin de mettre en place le téléchargement de données de mise à jour sur une application WPF.

BITS correspondait de façon rêvée à ce que je recherchais, restait à le mettre en place.

Dans ce petit article, je vais vous présenter la technologie, puis vous montrer un cas concret de mise en place de BITS dans vos projets.

 

 

 

  1. Définition

 

BITS (Background Intelligent Transfer Service) permet de transférer des fichiers (upload ou download) entre un client et un serveur, tout en fournissant les informations relatives à cet échange, tel que le pourcentage effectué.

De plus, BITS s’adapte à la bande passante. Imaginons que vous utilisiez déjà 60% de votre bande passante, BITS ne prendra jamais plus de 40%, dans le but de préserver le taux de réponse des autres applications. Ce transfert s’effectue en background, de façon transparente.

Pour finir, BITS va reprendre automatiquement les downloads après une coupure réseau par exemple, ou un redémarrage du pc.

 

 

BITS a bénéficié de différentes versions. La version actuelle (3.0) est installée d’office avec Vista et Longhorn.

La première version était dans Windows XP : Elle permettait de définir des downloads de façon priorisée, asynchrone, et de faire un « resume » après un problème technique.

 

Depuis, BITS a bien évolué, puisque la version 3.0 permet de plus :

-          d’uploader

-          de définir de façon concurrente plusieurs downloads en parallèle

-          d’utiliser SMB pour les noms distants

-          de limiter l’usage de la bande passante client

-          de gérer les header http

-          de gérer l’authentification par certificats ainsi qu’IPv6

-          d’avoir une notification une fois le download fini

-          de pouvoir accéder au fichier temporaire pendant le téléchargement

-          et d’autres encore etc…

 

Bref, ca a l’air super bien !

 


 

  1. Librairies disponibles

 

A l’origine, BITS avait été développé pour Windows 2003. De fait, Windows fournit une librairie pour les développeurs C et C++.

 

Cela veut donc dire qu’en .Net, ça ne sera pas direct. La DLL se trouve en fait dans %windir%\System32\QMgr.dll

 

Pour ceux qui développent en C ou en C++, une documentation est disponible par ici : http://msdn2.microsoft.com/en-us/library/aa362820.aspx

 

Par contre pour nos amis .Net, il reste 2 options :

-          faire un wrapper pour utiliser la DLL citée plus haut

-          se tourner vers une autre librairie : SharpBITS.

 

 

a)    Le Wrapper

 

Microsoft étant gentil, ils ont fourni un wrapper : http://msdn2.microsoft.com/en-us/library/ms997639.aspx. Cette page montre aussi quelques exemples de base, comme lancer un téléchargement.

 

 

b)    SharpBITS

 

 

SharpBits est une autre DLL, un autre wrapper. L’avantage de SharpBits, c’est qu’ils ont développé une application d’exemple qui est très bien faite, avec des exemples pour toutes les fonctionnalités de BITS, contrairement à la documentation Microsoft qui se limite aux docs en C et en C++. SharpBits GUI (l’application d’exemple) est disponible avec son code source ici : http://sharpbits.xidar.net/files/folders/sharpbits_gui/entry35.aspx

 

 

 

 

  1. BITS par la pratique

 

Loin de vouloir écrire un tutoriel complet sur comment faire ci et comment faire ça (je vous ai donné toutes les astuces plus haut pour que vous trouviez des exemples de code vous-même), je vais me limiter à présenter un code exemple de base :

 

Lancer un téléchargement :

 

        public BitsJob UpdateJob

        {

            get { return _updateJob; }

            set { _updateJob = value; }

        }

 

        public void StartDownload()

        {

            //nettoyer les jobs enventuellement en cours

            CleanBitsJobs();

            //lancer un nouveau job

            UpdateJob = manager.CreateJob(BITSJOB_DISPLAYNAME, JobType.Download);

            //assigner à ce job un fichier à télécharger

            UpdateJob.AddFile(ConfigurationManager.AppSettings["FileToDownload"], DataDirectory + "FileToDownload.zip");

            //définisson la priorité haute pour ce téléchargment

            UpdateJob.Priority = JobPriority.High;

            //évènements associés : erreur, transfert fini etc...

            UpdateJob.NotificationFlags = NotificationFlags.JobErrorOccured | NotificationFlags.JobTransferred | NotificationFlags.JobModified;

            UpdateJob.OnJobError += new EventHandler<JobErrorNotificationEventArgs>(UpdateJob_OnJobError);

            UpdateJob.OnJobModified += new EventHandler<JobNotificationEventArgs>(UpdateJob_OnJobModified);

            UpdateJob.OnJobTransferred += new EventHandler<JobNotificationEventArgs>(UpdateJob_OnJobTransferred);

            //lançons le job

            UpdateJob.Resume();

            UpdateState = UpdateState.Started;

        }

 

 

        public void CleanBitsJobs()

        {

            //récupérer tous les jobs existants pour l'utilisateur courant

            BitsJobs existingBitsJobs = manager.EnumJobs(JobOwner.CurrentUser);

            foreach (BitsJob existingBitsJob in existingBitsJobs.Values)

            {

                if (existingBitsJob.DisplayName == BITSJOB_DISPLAYNAME)

                {

                    //chaque job est annulé

                    existingBitsJob.Cancel();

                }

            }

        }

 

        private void UpdateJob_OnJobTransferred(object sender, JobNotificationEventArgs e)

        {

            //le transfert vient de finir, on mets à jour le statut

            UpdateJob.Complete();

            UpdateState = UpdateState.Ended;

        }

 

 

        private void UpdateJob_OnJobError(object sender, JobErrorNotificationEventArgs e)

        {

            //une erreur est parvenue, on log

            if (LOG.IsErrorEnabled)

            {

                LOG.Error(String.Format("{0} [{1}]", e.Error.Description, e.Error.ErrorCode));

            }

        }

 

        void UpdateJob_OnJobModified(object sender, JobNotificationEventArgs e)

        {

            //afficher le pourcentage du download en cours

            if (UpdateJob.Progress.BytesTotal > 0)

            {

                UpdateProgress = (UpdateJob.Progress.BytesTransferred * 100) / UpdateJob.Progress.BytesTotal;

            }

        }

 

 

  1. Pour aller plus loin

 

Voici une liste des problèmes connus de Microsoft éventuellement : http://support.microsoft.com/kb/331716

 





Accueil - Tutoriels & Articles - Liens - A Propos de l'auteur dotnet-tech.com : le site des technologies .net

www.dotnet-tech.com - 2003-2007