Comment établir une connexion à l’aide d’un socket de flux (HTML)

[ Cet article est destiné aux développeurs de Windows 8.x et Windows Phone 8.x qui créent des applications Windows Runtime. Si vous développez une application pour Windows 10, voir la Documentation ]

Cette rubrique montre comment faire en sorte qu’une application Windows Runtime puisse envoyer et recevoir des données réseau à l’aide d’un socket TCP en utilisant un StreamSocket. Un socket TCP fournit des transferts de données réseau de bas niveau dans chaque direction pour des connexions à durée de vie longue. Les sockets TCP sont la fonctionnalité sous-jacente utilisée par la plupart des protocoles réseau utilisés sur Internet.

Le composant client de l’exemple crée un socket TCP pour établir une connexion réseau, utilise ce socket pour envoyer des données, puis le ferme. Le composant serveur de l’exemple crée un socket TCP pour écouter et accepter des connexions réseau, accepte les connexions provenant du socket entrant, utilise le socket pour recevoir des données du client, puis le ferme. Cet exemple est fourni dans les langages de programmation JavaScript, C#, VB et C++.

Le composant client de l’exemple présente les fonctionnalités suivantes :

  • utiliser la classe StreamSocket pour créer un socket TCP ;
  • établir une connexion réseau à un serveur réseau TCP à l’aide de l’une des méthodes StreamSocket.ConnectAsync ;
  • envoyer des données au serveur à l’aide de l’objet Streams.DataWriter qui permet à un programmeur d’écrire des types courants (des entiers et des chaînes, par exemple) sur un flux ;
  • fermer le socket.

Le composant serveur de l’exemple présente les fonctionnalités suivantes :

Remarque  Pour utiliser cet exemple, vous devez disposer d’un accès réseau à l’aide de l’interface de bouclage.

 

Prérequis

Les exemples suivants utilisent JavaScript. Pour obtenir de l’aide sur la création de votre première application, voir Créer votre première application du Windows Store en JavaScript.

Pour préparer votre application du Windows Store à une mise en réseau, vous devez définir cette fonctionnalité dans le fichier Package.appxmanifest du projet. Pour obtenir une définition de chaque fonctionnalité réseau, voir Comment configurer les fonctionnalités d’isolement réseau.

Instructions

Créer un projet

  1. Ouvrez Microsoft Visual Studio 2013 et sélectionnez Nouveau projet dans le menu Fichier.
  2. Dans la liste des modèles, choisissez JavaScript.
  3. Sous la section, choisissez Store apps.
  4. Sous la section, sélectionnez Universal Apps, Windows apps, ou Windows Phone apps (en fonction de votre plateforme cible), puis Application vide.
  5. Nommez l’application socketsSample et cliquez sur OK.

Définir les fonctionnalités pour activer l’accès réseau

Vous devez définir les fonctionnalités réseau pour votre application si celle-ci a besoin d’un accès réseau. Les fonctionnalités réseau doivent être définies pour une application qui utilise un StreamSocket pour se connecter à un service réseau.

Si l’application doit être en mesure de se connecter en qualité de client à des services distants sur Internet, la fonctionnalité Internet (client) est alors nécessaire. Si l’application doit être en mesure de se connecter en qualité de client à des services distants sur un réseau domestique ou d’entreprise, la fonctionnalité Réseaux privés (client et serveur) est requise.

Si l’application doit utiliser le StreamSocketListener pour écouter les connexions entrantes à partir de points de terminaison distants sur Internet, la fonctionnalité Internet (client et serveur) est alors nécessaire. Si l’application doit utiliser le StreamSocketListener pour écouter les connexions entrantes à partir de points de terminaison distants sur un réseau domestique ou d’entreprise, la fonctionnalité Réseaux privés (client et serveur) est requise.

Remarque  Sur Windows Phone, une seule fonctionnalité réseau, Internet (client et serveur), permet à l’application d’accéder à tous les réseaux.

 

Si le composant serveur de cet exemple qui écoute les connexions entrantes s’exécute sur le même appareil que le composant client, un accès par bouclage s’avère nécessaire. Les applications développées et exécutées dans Visual Studio 2013 sont automatiquement inscrites comme n’étant pas concernées par les restrictions de bouclage. Pour plus d’informations, voir Comment activer le bouclage et déboguer l’isolement réseau.

Pour plus d’informations sur l’accès réseau, voir Comment configurer les fonctionnalités d’isolement réseau.

Ces étapes sont utiles pour définir les fonctionnalités réseau d’une application avant son déploiement si elle a accès à un service réseau sur Internet ou sur un réseau domestique ou d’entreprise.

  1. Utilisez Microsoft Visual Studio pour ouvrir le fichier package.appxmanifest.

  2. Sélectionnez l’onglet Capacités.

  3. Pour générer la version Windows de l’exemple, sélectionnez les fonctionnalités Internet (Client) et Réseaux privés (client et serveur).

    Pour générer la version Windows Phone de l’exemple, sélectionnez la fonctionnalité Internet (client et serveur).

  4. Enregistrez et fermez le fichier manifeste.

Ajouter une interface utilisateur HTML

  1. Ouvrez le dossier html. Ouvrez un nouveau fichier startListener.html, puis ajoutez le code HTML suivant dans les sections <head> et <body> du fichier.

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <script src="/js/socketsSample.js"></script>
        <script src="/js/startListener.js"></script>
    </head>
    <body>
        <div data-win-control="SdkSample.ScenarioInput">
            <p>
                StreamSocketListener will create the "server" side of a connection. It listens on
                a "service name" (often a port number) and calls a callback when it accepts a connection;
                this happens when some other application tries to connect. Once a connection is
                accepted, the acceptAsync() method needs to be called again.
            </p>
            <p>
                <label for="serviceNameAccept">Service Name:</label>
                <input id="serviceNameAccept" type="text" />
            </p>
            <p>
                <button id="buttonStartListener">Create StreamSocketListener and start to listen</button>
            </p>
        </div>
        <div data-win-control="SdkSample.ScenarioOutput">
            <p id="statusBox"></p>
            <p id="outputBox"></p>
        </div>
    </body>
    </html>
    
  2. Ouvrez le dossier html. Ouvrez un nouveau fichier connectToListener.html, puis ajoutez le code HTML suivant dans les sections <head> et <body> du fichier.

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <script src="/js/connectToListener.js"></script>
    </head>
    <body>
        <div data-win-control="SdkSample.ScenarioInput">
            <p>
                Next, you need the "other side of the connection" -- you need to connect to a listener.
                The host name and service name (often a port number) to connect to are the "Host
                Name:" and "Service Name:" entries. The service name should match what you started
                to listen to!
            </p>
            <p>
                The connection will automatically use IPv6 as needed. It will also resolve international
                domain names.
            </p>
            <p>
                Due to the network security system, you cannot connect to other applications running
                on the same machine. This means that you can only use "localhost" to connect to
                the same application (specifically, you can connect to a listener on the same machine
                running in the same app container)
            </p>
            <p>
                <label for="hostNameConnect">Host Name:</label>
                <input id="hostNameConnect" type="text" />
            </p>
            <p>
                <label for="serviceNameConnect">Service Name:</label>
                <input id="serviceNameConnect" type="text" />
            </p>
            <p>
                <button id="buttonOpen">Connect Now</button>
            </p>
        </div>
        <div data-win-control="SdkSample.ScenarioOutput">
            <p id="statusBox"></p>
            <p id="outputBox"></p>
        </div>
    </body>
    </html>
    
  3. Ouvrez le dossier html. Ouvrez un nouveau fichier sendData.html et ajoutez le code HTML suivant aux sections <head> et <body>.

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <script src="/js/sendData.js"></script>
    </head>
    <body>
        <div data-win-control="SdkSample.ScenarioInput">
            <p>
                Now you can send data to the "server". Sending data is often done with the DataWriter
                object; it will write to the socket stream. You can also hook up the socket stream
                to other streams in Windows 8.
            </p>
            <p>
                <button id="buttonSend">Send 'hello' now</button>
            </p>
        </div>
        <div data-win-control="SdkSample.ScenarioOutput">
            <p id="statusBox"></p>
            <p id="outputBox"></p>
        </div>
    </body>
    </html>
    
  4. Ouvrez le dossier html. Ouvrez un nouveau fichier closeSocket.html, puis ajoutez le code HTML suivant dans les sections <head> et <body> du fichier.

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <script src="/js/closeSocket.js"></script>
    </head>
    <body>
        <div data-win-control="SdkSample.ScenarioInput">
            <p>Lastly, you can close all sockets.</p>
            <p>If you don't close your socket, it will be closed for you when the application exits.</p>
            <p>
                <button id="buttonClose">Close all sockets</button>
            </p>
        </div>
        <div data-win-control="SdkSample.ScenarioOutput">
            <p id="statusBox"></p>
            <p id="outputBox"></p>
        </div>
    </body>
    </html>
    

Définir l’exemple et les scénarios

Le code présenté dans cette étape définit l’exemple, les fichiers HTML et les scénarios utilisés par l’exemple. Il ajoute également des détecteurs d’événements et démarre l’application. Les options du scénario permettent à l’utilisateur de démarrer l’écouteur de socket, de démarrer le client pour qu’il se connecte à l’écouteur, de faire en sorte que le client envoie des données au serveur et de fermer les sockets.

  • Ouvrez le dossier js. Ouvrez le fichier default.js et ajoutez-y le code suivant.

        var sampleTitle = "StreamSocket";
    
        var scenarios = [
            { url: "/html/startListener.html", title: "Start StreamSocketListener" },
            { url: "/html/connectToListener.html", title: "Connect to Listener" },
            { url: "/html/sendData.html", title: "Send Data" },
            { url: "/html/closeSocket.html", title: "Close Socket" }
        ];
    
        function activated(eventObject) {
            if (eventObject.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) {
                // Use setPromise to indicate to the system that the splash screen must not be torn down
                // until after processAll and navigate complete asynchronously.
                eventObject.setPromise(WinJS.UI.processAll().then(function () {
                    // Navigate to either the first scenario or to the last running scenario
                    // before suspension or termination.
                    var url = WinJS.Application.sessionState.lastUrl || scenarios[0].url;
                    return WinJS.Navigation.navigate(url);
                }));
            }
        }
    
        WinJS.Navigation.addEventListener("navigated", function (eventObject) {
            var url = eventObject.detail.location;
            var host = document.getElementById("contentHost");
            // Call unload method on current scenario, if there is one
            host.winControl && host.winControl.unload && host.winControl.unload();
            WinJS.Utilities.empty(host);
            eventObject.detail.setPromise(WinJS.UI.Pages.render(url, host, eventObject.detail.state).then(function () {
                WinJS.Application.sessionState.lastUrl = url;
            }));
        });
    
        WinJS.Namespace.define("SdkSample", {
            sampleTitle: sampleTitle,
            scenarios: scenarios
        });
    
        WinJS.Application.addEventListener("activated", activated, false);
        WinJS.Application.start();
    

Définir des variables pour les sockets et les fonctions d’événement

Le code présenté dans cette étape crée différentes variables, notamment le socket d’écoute, le socket client, le socket de lecture serveur et différentes variables pour les erreurs et événements. Des variables sont créées afin de suivre l’état du socket client (connecté ou en cours de fermeture). Cette étape définit également le nom d’hôte et le nom de service (port TCP) auxquels se connecter sur le serveur. Le nom d’hôte et le nom de service sont définis sur une valeur par défaut qui peut être modifiée dans l’interface utilisateur.

  • Ouvrez le dossier js. Ouvrez un nouveau fichier socketsSample.js et ajoutez-y le code suivant.

    var socketsSample = {};
    
    (function () {
        "use strict";
    
        socketsSample.listener = null; // A StreamSocketListener that acts as our server.
        socketsSample.serverSocket = null; // The server socket that's been accepted.
        socketsSample.serverReader = null; // The reader for the server socket.
        socketsSample.clientSocket = null; // The client socket that will connect to the server socket.
        socketsSample.connected = false;
        socketsSample.closing = false;
    
        socketsSample.serviceNameAccept = "22112";
        socketsSample.hostNameConnect = "localhost";
        socketsSample.serviceNameConnect = "22112";
    
        socketsSample.displayStatus = function (message) {
            document.getElementById("statusBox").innerHTML = message;
        };
    
        socketsSample.displayOutput = function (message) {
            document.getElementById("outputBox").innerHTML = message;
        };
    
        socketsSample.setValues = function () {
            var serviceNameAcceptInput = document.getElementById("serviceNameAccept");
            var hostNameConnectInput = document.getElementById("hostNameConnect");
            var serviceNameConnectInput = document.getElementById("serviceNameConnect");
    
            if (serviceNameAcceptInput) {
                serviceNameAcceptInput.value = socketsSample.serviceNameAccept;
            }
            if (hostNameConnectInput) {
                hostNameConnectInput.value = socketsSample.hostNameConnect;
            }
            if (serviceNameConnectInput) {
                serviceNameConnectInput.value = socketsSample.serviceNameConnect;
            }
        };
    
        socketsSample.getValues = function (evt) {
            switch (evt.target.id) {
                case "serviceNameAccept":
                    socketsSample.serviceNameAccept = evt.target.value;
                    break;
                case "hostNameConnect":
                    socketsSample.hostNameConnect = evt.target.value;
                    break;
                case "serviceNameConnect":
                    socketsSample.serviceNameConnect = evt.target.value;
                    break;
            }
        };
    })();
    

Créer un écouteur et démarrer l’écoute d’un nom de service (port)

Le code présenté dans cette étape crée un écouteur et démarre l’écoute. Des fonctions sont également ajoutées pour gérer les événements lorsque l’utilisateur demande que l’écouteur crée une liaison à une adresse IP et un port TCP, accepte une connexion et lise les données envoyées depuis le client.

Remarque  Dans cet exemple particulier, le client et le serveur se trouvent dans la même application, mais vous aurez généralement des applications cliente et serveur distinctes.

 

  • Ouvrez le dossier js. Ouvrez un nouveau fichier startListener.js, puis ajoutez le code suivant dans ce fichier :

        var page = WinJS.UI.Pages.define("/html/startListener.html", {
            ready: function (element, options) {
                document.getElementById("buttonStartListener").addEventListener("click", startListener, false);
                document.getElementById("serviceNameAccept").addEventListener("change", socketsSample.getValues, false);
                socketsSample.setValues();
            }
        });
    
        function startListener() {
            if (socketsSample.listener) {
                socketsSample.displayStatus("Already have a listener; call close to close the listener.");
                return;
            }
            socketsSample.closing = false;
            var serviceName = document.getElementById("serviceNameAccept").value;
            socketsSample.listener = new Windows.Networking.Sockets.StreamSocketListener(serviceName);
            socketsSample.listener.addEventListener("connectionreceived", onServerAccept);
            socketsSample.displayStatus("Server: listener creation started.");
            socketsSample.listener.bindServiceNameAsync(serviceName).done(function () {
                socketsSample.displayStatus("Server: listener creation completed.");
            }, onError);
        }
    
        // This has to be a real function ; it will "loop" back on itself with the
        // call to acceptAsync at the very end.
        function onServerAccept(eventArgument) {
            socketsSample.displayStatus("Server: connection accepted.");
            socketsSample.serverSocket = eventArgument.socket;
            socketsSample.serverReader = new Windows.Storage.Streams.DataReader(socketsSample.serverSocket.inputStream);
            startServerRead();
        }
    
        // The protocol here is simple: a four-byte 'network byte order' (big-endian) integer
        // that says how long a string is, and then a string that is that long.
        // We wait for exactly 4 bytes, read in the count value, and then wait for
        // count bytes, and then display them.
        function startServerRead() {
            socketsSample.serverReader.loadAsync(4).done(function (sizeBytesRead) {
                // Make sure 4 bytes were read.
                if (sizeBytesRead !== 4) {
                    socketsSample.displayStatus("Server: connection lost.");
                    return;
                }
    
                // Read in the 4 bytes count and then read in that many bytes.
                var count = socketsSample.serverReader.readInt32();
                return socketsSample.serverReader.loadAsync(count).then(function (stringBytesRead) {
                    // Make sure the whole string was read.
                    if (stringBytesRead !== count) {
                        socketsSample.displayStatus("Server: connection lost.");
                        return;
                    }
                    // Read in the string.
                    var string = socketsSample.serverReader.readString(count);
                    socketsSample.displayOutput("Server read: " + string);
                    // Restart the read for more bytes.
                    startServerRead();
                }); // End of "read in rest of string" function.
            }, onError);
        }
    
        function onError(reason) {
            // When we close a socket, outstanding async operations will be canceled and the
            // error callbacks called.  There's no point in displaying those errors.
            if (!socketsSample.closing) {
                socketsSample.displayStatus(reason);
            }
        }
    

Créer le socket et établir une connexion à un point de terminaison distant

Le code présenté dans cette étape ajoute une fonction permettant de créer le socket et d’établir une connexion au point de terminaison distant, généralement un serveur, à l’aide de la méthode StreamSocket.ConnectAsync. Une fonction est également ajoutée pour traiter les cas où une erreur se produit lorsque le client essaie d’établir une connexion.

  • Ouvrez le dossier js. Ouvrez un nouveau fichier connectToListener.js, puis ajoutez le code suivant dans ce fichier :

        var page = WinJS.UI.Pages.define("/html/connectToListener.html", {
            ready: function (element, options) {
                document.getElementById("buttonOpen").addEventListener("click", openClient, false);
                document.getElementById("hostNameConnect").addEventListener("change", socketsSample.getValues, false);
                document.getElementById("serviceNameConnect").addEventListener("change", socketsSample.getValues, false);
                socketsSample.setValues();
            }
        });
    
        function openClient() {
            if (socketsSample.clientSocket) {
                socketsSample.displayStatus("Already have a client; call close to close the listener and the client.");
                return;
            }
            socketsSample.closing = false;
            var serverHostName = new Windows.Networking.HostName(document.getElementById("hostNameConnect").value);
            var serviceName = document.getElementById("serviceNameConnect").value;
            socketsSample.clientSocket = new Windows.Networking.Sockets.StreamSocket();
            socketsSample.displayStatus("Client: connection started.");
            socketsSample.clientSocket.connectAsync(serverHostName, serviceName).done(function () {
                socketsSample.displayStatus("Client: connection completed.");
                socketsSample.connected = true;
            }, onError);
        }
    
        function onError(reason) {
            socketsSample.clientSocket = null;
    
            // When we close a socket, outstanding async operations will be canceled and the
            // error callbacks called.  There's no point in displaying those errors.
            if (!socketsSample.closing) {
                socketsSample.displayStatus(reason);
            }
        }
    

Envoyer et recevoir des données sur le client

Le code présenté dans cette étape ajoute une fonction permettant d’envoyer des données au serveur à l’aide des méthodes de la classe Windows.Storage.Stream.DataWriter.

  • Ouvrez le dossier js. Ouvrez un nouveau fichier sendData.js et ajoutez-y le code suivant.

        var page = WinJS.UI.Pages.define("/html/sendData.html", {
            ready: function (element, options) {
                document.getElementById("buttonSend").addEventListener("click", sendHello, false);
            }
        });
    
        function sendHello() {
            if (!socketsSample.connected) {
                socketsSample.displayStatus("Client: you must connect the client before using it.");
                return;
            }
            var writer = new Windows.Storage.Streams.DataWriter(socketsSample.clientSocket.outputStream);
            var string = "Hello World";
            var len = writer.measureString(string); // Gets the UTF-8 string length.
            writer.writeInt32(len);
            writer.writeString(string);
            socketsSample.displayStatus("Client sending: " + string + ".");
            writer.storeAsync().done(function () {
                socketsSample.displayStatus("Client sent: " + string + ".");
                writer.detachStream();
            }, onError);
        }
    
        function onError(reason) {
            // When we close a socket, outstanding async operations will be canceled and the
            // error callbacks called.  There's no point in displaying those errors.
            if (!socketsSample.closing) {
                socketsSample.displayStatus(reason);
            }
        }
    

Fermer les sockets

Le code présenté dans cette étape ferme le socket à l’aide de la méthode StreamSocket.Close. Lorsque les sockets sont fermés, toutes les opérations en attente sont terminées et les routines d’erreur sont appelées.

  • Ouvrez le dossier js. Ouvrez un nouveau fichier socketClose.js, puis ajoutez le code suivant dans ce fichier :

        var page = WinJS.UI.Pages.define("/html/closeSocket.html", {
            ready: function (element, options) {
                document.getElementById("buttonClose").addEventListener("click", closeListenerAndSockets, false);
            }
        });
    
        function closeListenerAndSockets() {
            socketsSample.closing = true;
            if (socketsSample.listener) {
                socketsSample.listener.close();
                socketsSample.listener = null;
            }
            if (socketsSample.serverSocket) {
                socketsSample.serverSocket.close();
                socketsSample.serverSocket = null;
            }
            if (socketsSample.clientSocket) {
                socketsSample.clientSocket.close();
                socketsSample.clientSocket = null;
                socketsSample.connected = false;
            }
            socketsSample.displayStatus("Client and server closed.");
        }
    

Exécuter l’application

  • Pour exécuter l’application, appuyez sur la touche F5 dans Visual Studio pour exécuter le projet. Sélectionnez les boutons dans l’ordre pour démarrer l’écouteur, connecter le client à l’écouteur, envoyer des données et fermer les sockets.

Récapitulatif et étapes suivantes

Dans cette rubrique, vous avez créé une application qui utilise un socket de flux TCP pour établir une connexion réseau et envoyer des données à l’aide d’un objet StreamSocket. Cette application a également permis de montrer comment écouter une connexion TCP et accepter une connexion à partir d’un socket de flux qui peut être utilisée pour l’envoi ou la réception de données.

Le code source et les fichiers de génération de cette rubrique sont disponibles dans l’exemple StreamSocket.

Vous pouvez également utiliser un socket datagramme pour établir une connexion réseau afin d’envoyer des données. Pour obtenir un exemple, voir Comment établir une connexion à l’aide d’un socket datagramme.

Rubriques associées

Autres ressources

Connexion à l’aide de sockets

Comment configurer les fonctionnalités réseau

Comment établir une connexion à l’aide d’un socket datagramme

Comment activer le bouclage et déboguer l’isolement réseau

Comment sécuriser des connexions de socket avec TLS/SSL

Comment définir des délais d’attente sur les opérations de socket

Comment utiliser des contrôles de socket avancés

Débogage et résolution des problèmes liés aux connexions réseau

Référence

StreamSocket

StreamSocketListener

Windows.Networking

Windows.Networking.Sockets

Windows.Storage.Stream.DataWriter

Exemples

Exemple StreamSocket