데이터그램 소켓을 사용하여 연결하는 방법(HTML)

[ 이 문서는 Windows 런타임 앱을 작성하는 Windows에서 8.x 및 Windows Phone 8.x 개발자를 대상으로 합니다. Windows 10용으로 개발하는 경우에는 최신 설명서를 참조하세요.]

이 항목에서는 UDP를 사용하여 DatagramSocket을 사용하는 Windows 런타임 앱에서 네트워크 데이터를 보내고 받는 방법을 보여 줍니다.

샘플의 클라이언트 구성 요소는 UDP 소켓을 만들고 이 소켓을 사용하여 데이터를 보내고 받은 다음 소켓을 닫습니다. 샘플의 서버 구성 요소는 UDP 소켓을 만들어 수신 네트워크 패킷을 수신 대기하고, 클라이언트에서 수신 UDP 패킷을 받고, 데이터를 클라이언트로 보낸 다음 소켓을 닫습니다. 이 샘플은 JavaScript, C# 및 C++ 프로그래밍 언어로 제공됩니다.

샘플의 클라이언트 구성 요소는 다음과 같은 기능을 보여 줍니다.

  • 클라이언트가 데이터를 보내고 받을 수 있도록 DatagramSocket 클래스를 사용하여 UDP 소켓을 만듭니다.
  • DatagramSocket 개체에서 UDP 데이터그램을 받았음을 나타내는 DatagramSocket.MessageReceived 이벤트에 대한 처리기를 추가합니다.
  • DatagramSocket.ConnectAsync 메서드 중 하나를 사용하여 패킷을 보내야 하는 UDP 네트워크 서버에 대한 원격 끝점을 설정합니다.
  • 프로그래머가 스트림에 일반적인 형식(정수 및 문자열 등)을 쓸 수 있도록 하는 Streams.DataWriter 개체를 사용하여 서버에 데이터를 보냅니다.
  • 소켓을 닫습니다.

샘플의 서버 구성 요소는 다음과 같은 기능을 보여 줍니다.

참고  이 샘플을 사용하려면 루프백 인터페이스를 사용하여 네트워크에 액세스해야 합니다.

 

목표: DatagramSocket 소켓을 사용하여 다른 컴퓨터 또는 장치에 대한 네트워크 연결을 만듭니다.

사전 요구 사항

다음 예에서는 JavaScript를 사용합니다. 첫 번째 앱을 만드는 자세한 내용은 JavaScript를 사용하여 첫 번째 Windows 스토어 앱 만들기를 참조하세요.

Windows 스토어 앱에서 네트워크에 대비하려면 프로젝트 Package.appxmanifest 파일에서 접근 권한 값을 설정해야 합니다. 각 네트워크 접근 권한 값에 대한 정의는 네트워크 격리 접근 권한 값을 구성하는 방법을 참조하세요.

지침

1. 새 프로젝트 만들기

  1. Microsoft Visual Studio 2013을 열고 파일 메뉴에서 새 프로젝트를 선택합니다.
  2. 템플릿 목록에서 JavaScript를 선택합니다.
  3. 섹션에서 Store apps을 선택합니다.
  4. 섹션에서 대상으로 하는 플랫폼에 따라 Universal Apps, Windows apps 또는 Windows Phone apps을 선택한 후 새 응용 프로그램을 선택합니다.
  5. 응용 프로그램 이름을 socketsSample로 지정하고 확인을 클릭합니다.

2. 네트워크 액세스를 사용하도록 하는 접근 권한 값 설정

앱에 네트워크 액세스가 필요한 경우 앱에 대해 네트워크 접근 권한 값을 설정해야 합니다. DatagramSocket을 사용하여 네트워크 서비스에 연결하는 앱은 네트워크 접근 권한 값을 설정해야 합니다.

앱이 인터넷의 원격 서비스에 클라이언트로 연결할 수 있으려면 인터넷(클라이언트) 접근 권한 값이 필요합니다. 앱이 홈 네트워크 또는 회사 네트워크의 원격 서비스에 클라이언트로 연결할 수 있어야 하는 경우 개인 네트워크(클라이언트 및 서버) 접근 권한 값이 필요합니다.

앱이 DatagramSocket를 사용하여 인터넷의 원격 끝점에서 수신 연결을 수신 대기해야 하는 경우 인터넷(클라이언트 및 서버) 접근 권한 값이 필요합니다. 앱이 DatagramSocket를 사용하여 홈 네트워크 또는 회사 네트워크의 원격 끝점에서 수신 연결을 수신 대기해야 하는 경우 개인 네트워크(클라이언트 및 서버) 접근 권한 값이 필요합니다.

참고  Windows Phone에는 앱에서 네트워크에 완전히 액세스하게 해 주는 단일 네트워크 접근 권한 값(인터넷(클라이언트 및 서버))이 있습니다.

 

수신 연결을 수신 대기하는 이 샘플의 서버 구성 요소가 클라이언트 구성 요소와 동일한 장치에서 실행되고 있는 경우 루프백 액세스가 필요합니다. Visual Studio 2013에서 개발되어 실행되는 앱은 루프백 제한이 면제되도록 자동으로 등록됩니다. 자세한 내용은 루프백을 사용하도록 설정하고 네트워크 격리를 디버그하는 방법을 참조하세요.

네트워크 액세스에 대한 자세한 내용은 네트워크 격리 접근 권한 값을 구성하는 방법을 참조하세요.

이 단계는 앱이 인터넷이나 홈 또는 회사 네트워크의 네트워크 서비스에 액세스하는 경우 배포되기 전에 앱의 네트워크 접근 권한 값을 설정하는 데 필요합니다.

  1. Microsoft Visual Studio를 사용하여 package.appxmanifest 파일을 엽니다.

  2. 접근 권한 값 탭을 선택합니다.

  3. Windows 버전 샘플을 빌드하려면 인터넷(클라이언트)개인 네트워크(클라이언트 및 서버) 접근 권한 값을 선택합니다.

    Windows Phone 버전 샘플을 빌드하려면 인터넷(클라이언트 및 서버) 접근 권한 값을 선택합니다.

  4. 매니페스트 파일을 저장하고 닫습니다.

3. HTML UI 추가

  1. html 폴더를 엽니다. 새 startListener.html 파일을 열고 <head> 및 <body> 섹션에 다음 HTML을 추가합니다.

    
    <!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>
                DatagramSocket is used to create the 'server' side of a connection. It listens on a 'service name' (often a port number) and 
                each time a datagram is received on the port number it fires MessageReceived event.
            </p>
            <p>
                <label for="serviceNameAccept">Service Name:</label>
                <input id="serviceNameAccept" type="text" />
            </p>
            <p>
                <button id="buttonStartListener">Listen</button>
            </p>
        </div>
        <div data-win-control="SdkSample.ScenarioOutput">
            <p id="statusBox"></p>
            <p id="outputBox"></p>
        </div>
    </body>
    </html>
    
  2. html 폴더를 엽니다. 새 connectToListener.html 파일을 열고 <head> 및 <body> 섹션에 다음 HTML을 추가합니다.

    <!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 internationalized
                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" disabled="disabled" />
            </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. html 폴더를 엽니다. 새 sendData.html 파일을 열고 <head> 및 <body> 섹션에 다음 HTML을 추가합니다.

    <!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.
            </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. html 폴더를 엽니다. 새 closeSocket.html 파일을 열고 <head> 및 <body> 섹션에 다음 HTML을 추가합니다.

    <!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>
    

4. 샘플 및 시나리오 정의

이 단계의 코드는 샘플, HTML 파일 및 샘플에서 사용하는 시나리오를 정의합니다. 이 코드는 또한 이벤트 수신기를 추가하고 앱을 시작합니다. 시나리오 옵션을 통해 사용자는 소켓 수신기를 시작하고, 클라이언트를 시작하여 수신기에 연결하고, 클라이언트가 일부 데이터를 서버로 보내도록 하고, 소켓을 닫을 수 있습니다.

  1. js 폴더를 엽니다. default.js 파일을 열고 파일에 다음 코드를 추가합니다.

        var sampleTitle = "DatagramSocket";
    
        var scenarios = [
            { url: "/html/startListener.html", title: "Start DatagramSocket Listener" },
            { 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();
    

5. 소켓 및 이벤트 함수에 대한 변수 정의

이 단계의 코드는 수신기 소켓, 클라이언트 소켓을 비롯한 다양한 변수와 오류 및 이벤트에 대한 다양한 변수를 만듭니다. 변수는 클라이언트 소켓이 연결된 상태 또는 닫힌 상태인지 여부를 추적하기 위해 만듭니다. 이 단계에서는 또한 연결할 호스트 이름과 서비스 이름(UDP 포트)을 정의하고 데이터를 보낼 뿐 아니라, 데이터를 수락하고 받을 로컬 서비스 이름(UDP 포트)도 정의합니다. 원격 호스트 이름, 원격 서비스 이름 및 로컬 서비스 이름의 값은 UI에서 변경할 수 있는 기본값으로 설정됩니다.

  • js 폴더를 엽니다. 새 socketsSample.js 파일을 열고 파일에 다음 코드를 추가합니다.

    var socketsSample = {};
    
    (function () {
        "use strict";
    
        socketsSample.listener = null;
        socketsSample.listenerOutputStream = null;
        socketsSample.listenerPeerAddress = null;
        socketsSample.listenerPeerPort = null;
        socketsSample.clientSocket = null;
        socketsSample.clientDataWriter = null;
        socketsSample.connected = false;
        socketsSample.closing = false;
        socketsSample.bindingToService = false;
    
        socketsSample.serviceNameAccept = "22112";
        socketsSample.hostNameConnect = "localhost";
        socketsSample.serviceNameConnect = "22112";
    
        socketsSample.close = function () {
    
            socketsSample.closing = true;
    
            if (socketsSample.listener) {
                socketsSample.listener.close();
            }
    
            if (socketsSample.clientSocket) {
                socketsSample.clientSocket.close();
            }
    
            socketsSample.listener = null;
            socketsSample.listenerOutputStream = null;
            socketsSample.listenerPeerAddress = null;
            socketsSample.listenerPeerPort = null;
            socketsSample.clientSocket = null;
            socketsSample.clientDataWriter = null;
            socketsSample.connected = false;
        };
    
        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;
            }
        };
    })();
    

6. 수신기 만들기 및 서비스 이름(포트) 수신 대기 시작

이 섹션의 코드는 수신기를 만들고 수신 대기를 시작합니다. 수신기가 IP 주소 및 UDP 포트에 바인딩되고, 연결을 수락하고, 클라이언트에서 보낸 데이터를 읽도록 사용자가 요청할 경우 이벤트를 처리하는 함수도 추가됩니다.

참고  이 특정 예제가 독립적(클라이언트 및 서버가 동일한 앱에 있음)일지라도 일반적으로는 클라이언트 앱과 서버 앱을 별도로 갖게 됩니다.

 

  • js 폴더를 엽니다. 새 startListener.js 파일을 열고 파일에 다음 코드를 추가합니다.

        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() {
            var serviceName = document.getElementById("serviceNameAccept").value;
            if (serviceName === "") {
                socketsSample.displayStatus("Please provide a service name.");
                return;
            }
    
            if (socketsSample.listener) {
                socketsSample.displayStatus("Already have a listener; call close to close the listener.");
                return;
            }
    
            socketsSample.closing = false;
            socketsSample.bindingToService = true;
            socketsSample.listener = new Windows.Networking.Sockets.DatagramSocket();
            socketsSample.listener.addEventListener("messagereceived", onServerMessageReceived);
            socketsSample.displayStatus("Server: listener creation started.");
            socketsSample.listener.bindServiceNameAsync(serviceName).done(function () {
                socketsSample.displayStatus("Server: listener creation completed.");
                socketsSample.bindingToService = false;
            }, onError);
        }
    
        function onServerMessageReceived(eventArgument) {
            if (socketsSample.listenerOutputStream) {
                echoMessage(socketsSample.listenerOutputStream, eventArgument);
                return;
            }
    
            socketsSample.listener.getOutputStreamAsync(eventArgument.remoteAddress, eventArgument.remotePort).done(function (outputStream) {
                if (!socketsSample.listenerOutputStream) {
                    socketsSample.listenerOutputStream = outputStream;
                    socketsSample.listenerPeerAddress = eventArgument.remoteAddress;
                    socketsSample.listenerPeerPort = eventArgument.remotePort;
                }
    
                echoMessage(socketsSample.listenerOutputStream, eventArgument);
            });
        }
    
        function echoMessage(outputStream, eventArgument) {
            if (socketsSample.listenerPeerAddress !== eventArgument.remoteAddress ||
                socketsSample.listenerPeerPort !== eventArgument.remotePort) {
                socketsSample.displayStatus("Got datagram from " + eventArguments.remoteAddress + ":" + eventArguments.remotePort +
                    ", but already 'connected' to " + socketsSample.listenerPeerAddress + ":" + socketsSample.listenerPeerPort);
                return;
            }
    
            outputStream.writeAsync(eventArgument.getDataReader().detachBuffer()).done(function () {
                // Do nothing - client will print out a message when data is received.
            });
        }
    
        function onError(reason) {
            // Clean up a listener if we failed to bind to a port.
            if (socketsSample.bindingToService) {
                socketsSample.listener = null;
                socketsSample.bindingToService = false;
            }
    
            // 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);
            }
        }
    

7. 소켓 만들기 및 원격 끝점에 연결

이 단계의 코드는 DatagramSocket.ConnectAsync 메서드를 사용하여 소켓을 만들고 원격 끝점(일반적으로 서버)에 연결하는 함수를 추가합니다. 클라이언트가 메시지를 받을 때 처리할 함수가 추가됩니다. 클라이언트가 연결하려고 할 때 오류가 있는 경우를 처리하기 위한 함수도 추가됩니다.

  • js 폴더를 엽니다. 새 connectToListener.js 파일을 열고 파일에 다음 코드를 추가합니다.

        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() {
            var serviceName = document.getElementById("serviceNameConnect").value;
            if (serviceName === "") {
                socketsSample.displayStatus("Please provide a service name.");
                return;
            }
    
            // By default 'hostNameConnect' is disabled and host name validation is not required. When enabling the text
            // box validating the host name is required since it was received from an untrusted source (user input).
            // Note that when enabling the text box users may provide names for hosts on the intErnet that require the
            // "Internet (Client)" capability.
            var hostName;
            try {
                hostName = new Windows.Networking.HostName(document.getElementById("hostNameConnect").value);
            } catch (error) {
                socketsSample.displayStatus("Error: Invalid host name.");
                return;
            }
    
            if (socketsSample.clientSocket) {
                socketsSample.displayStatus("Already have a client; call close to close the listener and the client.");
                return;
            }
    
            socketsSample.closing = false;
            socketsSample.clientSocket = new Windows.Networking.Sockets.DatagramSocket();
            socketsSample.clientSocket.addEventListener("messagereceived", onMessageReceived);
            socketsSample.displayStatus("Client: connection started.");
            socketsSample.clientSocket.connectAsync(hostName, serviceName).done(function () {
                socketsSample.displayStatus("Client: connection completed.");
                socketsSample.connected = true;
            }, onError);
        }
    
        function onMessageReceived(eventArgument) {
            try {
                var messageLength = eventArgument.getDataReader().unconsumedBufferLength;
                var message = eventArgument.getDataReader().readString(messageLength);
                socketsSample.displayStatus("Client: receive message from server \"" + message + "\"");
            } catch (exception) {
                status = Windows.Networking.Sockets.SocketError.getStatus(exception.number);
                if (status === Windows.Networking.Sockets.SocketErrorStatus.connectionResetByPeer) {
                    socketsSample.displayStatus("Peer does not listen on the specific port. Please make sure that you run step 1 first " +
                    "or you have a server properly working on a remote server.");
                } else {
                    socketsSample.displayStatus("Error happened when receiving a datagram: " + exception.message);
                }
            }
        }
    
        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);
            }
        }
    

8. 클라이언트에서 데이터 보내기 및 받기

이 단계의 코드는 Windows.Storage.Streams.DataWriter 클래스의 메서드를 사용하여 데이터를 원격 UDP 끝점으로 보내는 함수를 추가합니다.

  • js 폴더를 엽니다. 새 sendData.js 파일을 열고 파일에 다음 코드를 추가합니다.

        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;
            }
    
            if (!socketsSample.clientDataWriter) {
                socketsSample.clientDataWriter = new Windows.Storage.Streams.DataWriter(socketsSample.clientSocket.outputStream);
            }
    
            var string = "Hello World";
            socketsSample.clientDataWriter.writeString(string);
    
            socketsSample.displayStatus("Client sending: " + string + ".");
            socketsSample.clientDataWriter.storeAsync().done(function () {
                socketsSample.displayStatus("Client sent: " + string + ".");
            }, 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);
            }
        }
    

9. 소켓 닫기

이 단계의 코드는 DatagramSocket.Close 메서드를 사용하여 소켓을 닫습니다. 소켓이 닫히면 모든 보류 중인 작업이 종료되고 오류 루틴이 호출됩니다.

  • js 폴더를 엽니다. 새 socketClose.js 파일을 열고 파일에 다음 코드를 추가합니다.

        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;
            }
    
            if (!socketsSample.clientDataWriter) {
                socketsSample.clientDataWriter = new Windows.Storage.Streams.DataWriter(socketsSample.clientSocket.outputStream);
            }
    
            var string = "Hello World";
            socketsSample.clientDataWriter.writeString(string);
    
            socketsSample.displayStatus("Client sending: " + string + ".");
            socketsSample.clientDataWriter.storeAsync().done(function () {
                socketsSample.displayStatus("Client sent: " + string + ".");
            }, 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);
            }
        }
    

10. 응용 프로그램 실행

  • 앱을 실행하려면 Visual Studio에서 F5 키를 눌러 프로젝트를 실행합니다. 수신기를 시작하고, 클라이언트를 수신기에 연결하고, 데이터를 보내고, 소켓을 닫으려면 해당 단추를 선택합니다.

요약 및 다음 단계

이 항목에서는 UDP 데이터그램 소켓을 사용하여 네트워크에 연결하고 DatagramSocket 개체를 사용하여 데이터를 보내는 앱을 만들었습니다. 또한 이 앱이 UDP 포트를 수신 대기하고 데이터를 받는 방법을 살펴봤습니다.

이 항목의 소스 코드 및 빌드 파일은 DatagramSocket 샘플로 제공됩니다.

스트림 소켓을 사용하여 데이터를 보내고 받는 데 사용되는 네트워크 연결을 설정할 수도 있습니다. 이에 대한 예는 스트림 소켓을 사용하여 연결하는 방법을 참조하세요.

관련 항목

다른 리소스

소켓을 사용하여 연결

네트워크 격리 접근 권한 값을 구성하는 방법

스트림 소켓을 사용하여 연결하는 방법

소켓 작업에 시간 제한을 설정하는 방법

고급 소켓 컨트롤을 사용하는 방법

네트워크 연결 문제 해결 및 디버그

참조

DatagramSocket

Windows.Networking

Windows.Networking.Sockets

샘플

DatagramSocket 샘플