情報
要求されたトピックは次のとおりです。しかし、このトピックはこのライブラリには含まれていません。

Windows Phone 8 の TCP ソケット クライアント アプリを作成および使用する方法

2014/06/18

対象: Windows Phone 8 および Windows Phone Silverlight 8.1 | Windows Phone OS 7.1

 

このトピックでは、Windows Phone 用のシンプルな TCP ソケット クライアント アプリを作成するのに必要な手順について説明します。一般的なシナリオでは、クライアント アプリが TCP ソケット接続を通じてサーバーと通信します。説明を単純にして、このトピックを自己完結させるために、コンピューターに組み込まれている簡易 TCP/IP サービスを、この通信のサーバー側として使用します。UDP ソケットを使用して同様のクライアント アプリを作成する場合は、「Windows Phone 8 の UDP ソケット クライアント アプリを作成および使用する方法」を参照してください。

重要:重要:

このトピックでは、クライアント通信で TCP ソケット サーバーを使用する必要があります。この例では、Windows の簡易 TCP/IP サービス機能をサーバー コンポーネントとして使用しています。次の手順は、コンピューター上で簡易 TCP/IP サービス機能を有効にする方法を示しています。独自のソケット サーバーの実装を使用することもできます。

このトピックは、次のセクションで構成されています。

 

このセクションでは、TCP ソケット クライアントの機能を示すための UI を作成します。

TCP ソケット クライアント UI を作成するには

  1. Visual Studio で、[ファイル] メニューの [新しいプロジェクト] をクリックして新しいプロジェクトを作成します。

  2. [新しいプロジェクト] ウィンドウが表示されます。Visual C# のテンプレートを展開し、Windows Phone のテンプレートを選択します。

  3. Windows Phone アプリ のテンプレートを選択します。[名前] に選択した名前を入力します。

  4. [OK] をクリックします。Windows Phone プラットフォームの選択ダイアログ ボックスが表示されます。対象のバージョンを選択するか、既定値を受け入れます。

  5. [OK] をクリックします。新しいプロジェクトが作成され、Visual Studio のデザイナー ウィンドウに MainPage.xaml が表示されます。

  6. MainPage.xaml で、"TitlePanel" という名前の StackPanel の XAML コードを削除し、次のコードに置き換えます。

    
    <!--TitlePanel contains the name of the application and page title-->
    <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
        <TextBlock x:Name="ApplicationTitle" Text="TCP Socket Application" Style="{StaticResource PhoneTextNormalStyle}"/>
        <TextBlock x:Name="PageTitle" Text="Client" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
    </StackPanel>
    
    
    

    この XAML コードは、2 つの TextBlock 要素をアプリに追加します。1 つは "ApplicationTitle" というアプリ タイトル用、もう 1 つは "PageTitle" というページ タイトル用です。

  7. MainPage.xaml で、"ContentPanel" という名前のグリッドの XAML コードを削除し、次のコードに置き換えます。

    
    <!--ContentPanel - place additional content here-->
    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,-8,12,8">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>    <!-- Fit to content -->
            <ColumnDefinition Width="Auto"/>    <!-- Fit to content -->
            <ColumnDefinition Width="Auto"/>    <!-- Fit to content -->
            <ColumnDefinition Width="*"/>       <!-- Take up remaining space -->
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>      <!-- Fit to content -->
            <RowDefinition Height="Auto"/>      <!-- Fit to content -->
            <RowDefinition Height="Auto"/>      <!-- Fit to content -->
            <RowDefinition Height="*"/>         <!-- Take up remaining space -->
        </Grid.RowDefinitions>
        
        <!-- Grid Row 0: Remote Host Input Field >-->
        <TextBlock Grid.Row="0" Grid.Column="0" Text="Host Name:"  
                   VerticalAlignment="Center" HorizontalAlignment="Center" 
                   FontSize="{StaticResource PhoneFontSizeNormal}" />
        <TextBox x:Name="txtRemoteHost" Grid.Row="0" Grid.Column="1"  Height="70" Width="200" 
         VerticalAlignment="Top" HorizontalAlignment="Left" 
         FontSize="{StaticResource PhoneFontSizeNormal}"  />
              
        <!-- Grid Row 1: Echo >-->
        <!-- TextBlock for Echo command label-->
        <TextBlock Grid.Row="1" Grid.Column="0" Text="Text To Echo:" 
                   VerticalAlignment="Center" HorizontalAlignment="Center" 
                   FontSize="{StaticResource PhoneFontSizeNormal}" />
              
        <!-- TextBox for Echo command text input-->
        <TextBox x:Name="txtInput" Grid.Row="1" Grid.Column="1" Height="70" Width="200"  
                 VerticalAlignment="Top" HorizontalAlignment="Left" 
                 FontSize="{StaticResource PhoneFontSizeNormal}" />
               
        <!-- Button to the right of the input textbox for the Echo command >-->
        <Button x:Name="btnEcho" Grid.Row="1" Grid.Column="2" Height="70"  Width="120" 
                Content="Echo" 
                FontSize="{StaticResource PhoneFontSizeNormal}" Click="btnEcho_Click"/>
                
        <!-- Grid Row 2: Quote of the Day-->
        <!-- Button for the Quote command >-->
        <Button x:Name="btnGetQuote" Grid.Row="2" Grid.ColumnSpan="4" Height="70" 
                Content="Get Quote of the Day" 
                FontSize="{StaticResource PhoneFontSizeNormal}" Click="btnGetQuote_Click"/>
    
        <!-- Grid Row 3: Output-->
        <!-- Output TextBox named 'txtOutput' >-->
        <TextBox x:Name="txtOutput" Grid.Row="3" Grid.ColumnSpan="4" Background="Black" BorderBrush="Green" 
                 AcceptsReturn="False" Foreground="LightGray" FontFamily="Courier New"  
                 IsHitTestVisible="False" FontSize="{StaticResource PhoneFontSizeSmall}" TextWrapping="Wrap" />
    </Grid>
    
    

    この XAML コードは、その他すべての要素を含めるための Grid 要素を作成します。最初に、3 つの行と 3 つの列を含む Grid を定義します。次に、リモート ホスト名のデータ入力のための TextBox を定義し、TextBlock をこのフィールドのラベルとして定義します。Gridの次の行は、ユーザーによる追加データ入力用の別の TextBox と、Click イベント ハンドラーが割り当てられた 2 つの Button 要素で構成されています。最後に、アプリからの出力を表示するためのもう 1 つの TextBox を定義します。以降のセクションでは、btnEcho_Click メソッドと btnGetQuote_Click メソッドを実装します。デザイナーでのレイアウトは次のようになります。

    Socket Sample Screenshot

ここでは、System.Net.Sockets API を使用して、ソケットを作成し、サーバーに接続します。わかりやすくするために、System.Net.Sockets API の呼び出しは、SocketClient クラス内にカプセル化されています。

TCP ソケット サーバーに接続するには

  1. ソリューション エクスプローラー ウィンドウでプロジェクトを選択し、右クリックしてコンテキスト メニューから [追加]、[クラス] の順にクリックして新しいクラスを作成します。これによって、クラス テンプレートが選択された状態で、[新しい項目の追加] ダイアログ ボックスが表示されます。[名前] フィールドでクラスの名前を "SocketClient" に変更し、[追加] をクリックします。プロジェクトに、"SocketClient" という名前の新しいクラスが作成されます。

  2. SocketClient.cs を開き、ページの先頭に次の using ディレクティブを追加します。

    
    using System.Net.Sockets;
    using System.Threading;
    using System.Text;
    
    
  3. SocketClient クラスの先頭で、次の変数を定義します。

    
    // Cached Socket object that will be used by each call for the lifetime of this class
            Socket _socket = null;
    
            // Signaling object used to notify when an asynchronous operation is completed
            static ManualResetEvent _clientDone = new ManualResetEvent(false);
    
            // Define a timeout in milliseconds for each asynchronous call. If a response is not received within this 
            // timeout period, the call is aborted.
            const int TIMEOUT_MILLISECONDS = 5000;
    
            // The maximum size of the data buffer to use with the asynchronous socket methods
            const int MAX_BUFFER_SIZE = 2048;
    
    

    _socket 変数は、作成した Socket オブジェクトを格納するために使用されます。_clientDone 変数は ManualResetEvent であり、System.Net.Sockets API で呼び出される非同期呼び出しの調整に使用されます。

  4. SocketClient.cs で、次のメソッドを追加します。このメソッドは TCP ソケットを作成し、非同期接続リクエストをサーバーに送信します。このアクションの応答は、インライン コールバックによって処理されます。

    
            /// <summary>
            /// Attempt a TCP socket connection to the given host over the given port
            /// </summary>
            /// <param name="hostName">The name of the host</param>
            /// <param name="portNumber">The port number to connect</param>
            /// <returns>A string representing the result of this connection attempt</returns>
            public string Connect(string hostName, int portNumber)
            {
                string result = string.Empty;
    
                // Create DnsEndPoint. The hostName and port are passed in to this method.
                DnsEndPoint hostEntry = new DnsEndPoint(hostName, portNumber);
    
                // Create a stream-based, TCP socket using the InterNetwork Address Family. 
                _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                
                // Create a SocketAsyncEventArgs object to be used in the connection request
                SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
                socketEventArg.RemoteEndPoint = hostEntry;
    
                // Inline event handler for the Completed event.
                // Note: This event handler was implemented inline in order to make this method self-contained.
                socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e)
                {
                    // Retrieve the result of this request
                    result = e.SocketError.ToString();
    
                    // Signal that the request is complete, unblocking the UI thread
                    _clientDone.Set();
                });
    
                // Sets the state of the event to nonsignaled, causing threads to block
                _clientDone.Reset();
    
                // Make an asynchronous Connect request over the socket
                _socket.ConnectAsync(socketEventArg);
    
                // Block the UI thread for a maximum of TIMEOUT_MILLISECONDS milliseconds.
                // If no response comes back within this time then proceed
                _clientDone.WaitOne(TIMEOUT_MILLISECONDS);
    
                return result;
            }
    
    
    

    このメソッドは、次の概念を示します。

    • エンドポイントの作成: DnsEndPoint クラスには、アプリがホスト上のサービスに接続するために必要なホスト名、または IP アドレスとリモート ポートの情報が格納されます。

    • ソケットの作成: Socket オブジェクトをインスタンス化するために、AddressFamily パラメーターを AddressFamily.InterNetwork に、SocketType パラメーターを SocketType.Stream に、および ProtocolType パラメーターを ProtocolType.Tcp に設定します。AddressFamily パラメーターは、Socket がアドレスを解決するために使用するアドレッシング スキームを指定します。たとえば、AddressFamily.InterNetwork は、ソケットをエンド ポイントに接続する場合に、IP version 4 アドレスが必要であることを示します。ソケット接続はまだ確立されていないことに注意してください。現在はソケットを、TCP プロトコルを使用するストリームベースのソケットとして設定しているだけです。サーバーへの実際の接続は、ConnectAsync を呼び出したときに試行されます。

      重要:重要:

      Windows Phone OS 7.1 で、Socket コンストラクターの パラメーターに指定できる値は、InterNetwork のみです。AddressFamily 列挙値の他のいずれかのメンバーを選択すると、エラーが発生します。

    • コンテキスト オブジェクトを作成する: このオブジェクトは呼び出される非同期メソッド (この場合は ConnectAsync) のコンテキスト オブジェクトです。データ バッファー、コールバック メソッド、その他のさまざまなコンテキスト固有のデータは、このオブジェクトで設定され、非同期呼び出しに渡されます。呼び出しが完了すると、このオブジェクトで完了状態および操作の結果を確認できます。

    • Completed イベントのコールバックを定義する: このメソッドは、ConnectAsync メソッドからの Completed イベントを処理するためにデリゲートを使用します。

    • 呼び出しが完了するまで待機する: この例では、Completed イベントが発生するか、呼び出しがタイムアウトになるまで、WaitOne メソッドは UI スレッドをブロックします。

    メモメモ:

    アプリが休止状態から再アクティブ化された場合、ソケットの新しいインスタンスを作成する必要はありません。接続を再び確立するには、ConnectAsync を呼び出します。ソケットに接続の優先順位や要件が定義されている場合、休止状態の間、それらが維持されます。 実行モデルとアプリの状態の詳細については、「Windows Phone 8 のアプリのアクティブ化および非アクティブ化」を参照してください。

このセクションでは、データをサーバーに送信するために、Send メソッドを SocketClient クラスに追加します。

TCP ソケット サーバーにデータを送信するには

  • SocketClient.cs に、次のメソッドを追加します。

       
    /// <summary>
    /// Send the given data to the server using the established connection
    /// </summary>
    /// <param name="data">The data to send to the server</param>
    /// <returns>The result of the Send request</returns>
    public string Send(string data)
    {
        string response = "Operation Timeout";
    
        // We are re-using the _socket object initialized in the Connect method
        if (_socket != null)
        {
            // Create SocketAsyncEventArgs context object
            SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
    
            // Set properties on context object
            socketEventArg.RemoteEndPoint = _socket.RemoteEndPoint;
            socketEventArg.UserToken = null;
    
            // Inline event handler for the Completed event.
            // Note: This event handler was implemented inline in order 
            // to make this method self-contained.
            socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e)
            {
                response = e.SocketError.ToString();
    
                // Unblock the UI thread
                _clientDone.Set();
            });
    
            // Add the data to be sent into the buffer
            byte[] payload = Encoding.UTF8.GetBytes(data);
            socketEventArg.SetBuffer(payload, 0, payload.Length);
    
            // Sets the state of the event to nonsignaled, causing threads to block
            _clientDone.Reset();
    
            // Make an asynchronous Send request over the socket
            _socket.SendAsync(socketEventArg);
    
            // Block the UI thread for a maximum of TIMEOUT_MILLISECONDS milliseconds.
            // If no response comes back within this time then proceed
            _clientDone.WaitOne(TIMEOUT_MILLISECONDS);
        }
        else
        {
            response = "Socket is not initialized";
        }
    
        return response;
    }
    
    

    このメソッドは、次の概念を示します。

    • コンテキスト オブジェクトを作成する: このオブジェクトは呼び出される非同期メソッド (この場合は SendAsync) のコンテキスト オブジェクトです。データ バッファー、コールバック メソッド、その他のさまざまなコンテキスト固有のデータは、このオブジェクトで設定され、非同期呼び出しに渡されます。呼び出しが完了した段階で、このオブジェクトの完了ステータスと操作の結果を調べることができます。

    • コンテキスト オブジェクトにバッファーを設定する: サーバーに送信されるデータは、バイトの配列として、SocketAsyncEventArgs オブジェクトのバッファーに配置されます。

    • Completed イベントのコールバックを定義する: このメソッドは、SendAsync 呼び出しからの Completed イベントを処理するためにデリゲートを使用します。

    • 呼び出しが完了するまで待機する: この例で、WaitOne メソッドは、Completed イベントが発生するか、呼び出しがタイムアウトするまで、UI スレッドをブロックします。

このセクションでは、データをサーバーに送信するために、Receive メソッドを SocketClient クラスに追加します。

TCP ソケット サーバーからデータを受信するには

  • SocketClient.cs に、次のコードを追加します。

    
    /// <summary>
    /// Receive data from the server using the established socket connection
    /// </summary>
    /// <returns>The data received from the server</returns>
    public string Receive()
    {
        string response = "Operation Timeout";
    
        // We are receiving over an established socket connection
        if (_socket != null)
        {
            // Create SocketAsyncEventArgs context object
            SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
            socketEventArg.RemoteEndPoint = _socket.RemoteEndPoint;
    
            // Setup the buffer to receive the data
            socketEventArg.SetBuffer(new Byte[MAX_BUFFER_SIZE], 0, MAX_BUFFER_SIZE);
    
            // Inline event handler for the Completed event.
            // Note: This even handler was implemented inline in order to make 
            // this method self-contained.
            socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e)
            {
                if (e.SocketError == SocketError.Success)
                {
                    // Retrieve the data from the buffer
                    response = Encoding.UTF8.GetString(e.Buffer, e.Offset, e.BytesTransferred);
                    response = response.Trim('\0');
                }
                else
                {
                    response = e.SocketError.ToString();
                }
    
                _clientDone.Set();
            });
    
            // Sets the state of the event to nonsignaled, causing threads to block
            _clientDone.Reset();
    
            // Make an asynchronous Receive request over the socket
            _socket.ReceiveAsync(socketEventArg);
    
            // Block the UI thread for a maximum of TIMEOUT_MILLISECONDS milliseconds.
            // If no response comes back within this time then proceed
            _clientDone.WaitOne(TIMEOUT_MILLISECONDS);
        }
        else
        {
            response = "Socket is not initialized";
        }
    
        return response;
    }
    
    /// <summary>
    /// Closes the Socket connection and releases all associated resources
    /// </summary>
    public void Close()
    {
        if (_socket != null)
        {
            _socket.Close();
        }
    }
    
    
    

    このメソッドは、次の概念を示します。

    • コンテキスト オブジェクトを作成する: このオブジェクトは呼び出される非同期メソッド (この場合は ReceiveAsync) のコンテキスト オブジェクトです。データ バッファー、コールバック メソッド、その他のさまざまなコンテキスト固有のデータは、このオブジェクトで設定され、非同期呼び出しに渡されます。呼び出しが完了すると、このオブジェクトで完了状態および操作の結果を確認できます。

    • コンテキスト オブジェクトにバッファーを設定する: サーバーから受信するデータは、バイトの配列として、SocketAsyncEventArgs オブジェクトのバッファーに配置されます。

    • Completed イベントのコールバックを定義する: このメソッドは、ReceiveAsync 呼び出しからの Completed イベントを処理するためにデリゲートを使用します。

    • 呼び出しが完了するまで待機する: この例で、Connect メソッドは、Completed イベントが発生するか、呼び出しがタイムアウトするまでブロックします。

    • Close メソッド:クライアント アプリで、作成された Socket を明示的に閉じるには、Close メソッドを SocketClient クラスに追加します。

前のセクションでは、ストリームベースの TCP ソケットを通じてサーバーと通信するのに必要なすべての操作をカプセル化するために、SocketClient クラスを実装しました。ここで、クライアント アプリに戻り、この SocketClient クラスを使用するために必要な機能を追加します。このアプリはコンピューター上の Echo サービスおよび Quote of the Day (QOTD) サービスと通信します。Echo サービスは、このサービスに送信されたすべてのデータをエコー バックします。Quote of the Day サービスは、メッセージで、1 行または複数行のテキストから成る引用を返します。btnEchoボタンおよび btnGetQuote ボタンからの Click イベント用のイベント ハンドラーを追加します。また、txtOutput TextBox への出力を実行するメソッドと、txtRemoteHost 要素および txtInput TextBox 要素からの入力を検証するためのメソッドを追加します。

アプリで SocketClient クラスを使用するには

  1. MainPage.xaml.cs クラスの先頭で、次の定数を定義します。

    
    // Constants
    const int ECHO_PORT = 7;  // The Echo protocol uses port 7 in this sample
    const int QOTD_PORT = 17; // The Quote of the Day (QOTD) protocol uses port 17 in this sample
    
    
  2. MainPage.xaml.cs に、次のコードを追加します。

    
    /// <summary>
    /// Handle the btnEcho_Click event by sending text to the echo server 
    /// and outputting the response
    /// </summary>
    private void btnEcho_Click(object sender, RoutedEventArgs e)
    {
        // Clear the log 
        ClearLog();
    
        // Make sure we can perform this action with valid data
        if (ValidateRemoteHost() && ValidateInput())
        {
            // Instantiate the SocketClient
            SocketClient client = new SocketClient();
            
            // Attempt to connect to the echo server
            Log(String.Format("Connecting to server '{0}' over port {1} (echo) ...", txtRemoteHost.Text, ECHO_PORT), true);
            string result = client.Connect(txtRemoteHost.Text, ECHO_PORT);
            Log(result, false);
    
            // Attempt to send our message to be echoed to the echo server
            Log(String.Format("Sending '{0}' to server ...", txtInput.Text), true);
            result = client.Send(txtInput.Text);
            Log(result, false);
    
            // Receive a response from the echo server
            Log("Requesting Receive ...", true);
            result = client.Receive();
            Log(result, false);
    
            // Close the socket connection explicitly
            client.Close();
        }
    
    }
    
    /// <summary>
    /// Handle the btnEcho_Click event by receiving text from the Quote of 
    /// the Day (QOTD) server and outputting the response 
    /// </summary>
    private void btnGetQuote_Click(object sender, RoutedEventArgs e)
    {
        // Clear the log 
        ClearLog();
    
        // Make sure we can perform this action with valid data
        if (ValidateRemoteHost())
        {
            // Instantiate the SocketClient object
            SocketClient client = new SocketClient();
    
            // Attempt connection to the Quote of the Day (QOTD) server
            Log(String.Format("Connecting to server '{0}' over port {1} (Quote of the Day) ...", txtRemoteHost.Text, QOTD_PORT), true);
            string result = client.Connect(txtRemoteHost.Text, QOTD_PORT);
            Log(result, false);
    
            // Note: The QOTD protocol is not expecting data to be sent to it.
            // So we omit a send call in this example.
    
            // Receive response from the QOTD server
            Log("Requesting Receive ...", true);
            result = client.Receive();
            Log(result, false);
    
            // Close the socket conenction explicitly
            client.Close();
        }
    }
    
    #region UI Validation
    /// <summary>
    /// Validates the txtInput TextBox
    /// </summary>
    /// <returns>True if the txtInput TextBox contains valid data, otherwise 
    /// False.
    ///</returns>
    private bool ValidateInput()
    {
        // txtInput must contain some text
        if (String.IsNullOrWhiteSpace(txtInput.Text))
        {
            MessageBox.Show("Please enter some text to echo");
             return false;
         }
    
        return true;
    }
    
    /// <summary>
    /// Validates the txtRemoteHost TextBox
    /// </summary>
    /// <returns>True if the txtRemoteHost contains valid data,
    /// otherwise False
    /// </returns>
    private bool ValidateRemoteHost()
    {
        // The txtRemoteHost must contain some text
        if (String.IsNullOrWhiteSpace(txtRemoteHost.Text))
        {
            MessageBox.Show("Please enter a host name");
            return false;
        }
    
        return true;
    }
    #endregion
    
    #region Logging
    /// <summary>
    /// Log text to the txtOutput TextBox
    /// </summary>
    /// <param name="message">The message to write to the txtOutput TextBox</param>
    /// <param name="isOutgoing">True if the message is an outgoing (client to server)
    /// message, False otherwise.
    /// </param>
    /// <remarks>We differentiate between a message from the client and server 
    /// by prepending each line  with ">>" and "<<" respectively.</remarks>
    private void Log(string message, bool isOutgoing)
    {
        string direction = (isOutgoing) ? ">> " : "<< ";
        txtOutput.Text += Environment.NewLine + direction + message;
    }
    
    /// <summary>
    /// Clears the txtOutput TextBox
    /// </summary>
    private void ClearLog()
    {
        txtOutput.Text = String.Empty;
    }
    #endregion
     
    

    前のコードでは、Echo 操作は次のように実装されています。

    • btnEcho ボタンの Click イベントを処理する: Echo 操作は、btnEcho_Click イベントで実装されています。Echo 操作は、ソケットに対する ConnectSend、および Receive 操作で構成されます。これは、Connect 操作と Receive 操作のみを使用する GetQuote 操作とは異なります。

    • SocketClient オブジェクトのスコープをメソッドにする: この処理は、Echo と GetQuote の呼び出しを単純にし、自己完結性を維持するために実行されます。SocketClient クラスのインスタンスは、クラス スコープに格納して、再利用することもできます。

    • 定数としてのポート番号: このサンプルでは、クライアントは既知のポート番号 7 を使用して Echo プロトコルに接続します。このポート番号は、MainPage.xaml.cs クラスで ECHO_PORT として定義されています。

    • Connect: これは、SocketClientConnect メソッドを呼び出す際に、txtRemoteHost で受信したホスト名と、ECHO_PORT 定数で定義されたポート番号を渡すことによって行われます。入力は検証され、この操作からのフィードバックは Log メソッドを使用することによって、txtOutput に書き込まれます。

    • 送信: txtInput フィールド内のテキストは、SocketClient オブジェクトの Send メソッドを使用することによって、サーバーに送信されます。入力は検証され、この操作からのフィードバックは Log メソッドを使用することによって、txtOutput に書き込まれます。

    • 受信: 次に、SocketClient オブジェクトの Receive メソッドを呼び出すことによって、エコー サーバーからのデータが受信されます。これは、Log メソッドを使用することによって、txtOutput に書き込まれます。

    • 閉じる: 最後に、SocketClient オブジェクトの Close メソッドを明示的に呼び出してソケットを閉じます。

    GetQuote 操作は上記のコードで、次のように実装しています。

    • btnGetQuote ボタンの Click イベントを処理する: GetQuote 操作は、btnGetQuote_Click イベントで実装されています。GetQuote 操作は、ソケットに対する Connect 操作と Receive 操作で構成されます。これは、ConnectSend、および Receive の各操作を使用する Echo 操作とは異なります。

    • SocketClient オブジェクトのスコープをメソッドにする: この処理は、Echo と GetQuote の呼び出しを単純にし、自己完結性を維持するために実行されます。SocketClient クラスのインスタンスは、クラス スコープに格納して、再利用することもできます。

    • 定数としてのポート番号: このサンプルでは、クライアントは既知のポート番号 17 を使用して Quote of the Day (QOTD) プロトコルに接続します。このポート番号は、MainPage.xaml.cs クラスで QOTD_PORT として定義されています。

    • Connect: これは、SocketClientConnect メソッドを呼び出す際に、txtRemoteHost で受信したホスト名と、QOTD_PORT 定数で定義されたポート番号を渡すことによって行われます。入力は検証され、この操作からのフィードバックは Log メソッドを使用することによって、txtOutput に書き込まれます。

    • 送信: Quote of the Day の場合、送信要求は行われません。Receive 要求を使用して、サーバーから引用をプルするだけです。

    • 受信: 次に、SocketClient オブジェクトの Receive メソッドを呼び出すことによって、Quote of the Day サーバーからのデータが受信されます。これは、Log メソッドを使用することによって、txtOutput に書き込まれます。

    • 閉じる: 最後に、SocketClient オブジェクトの Close メソッドを明示的に呼び出してソケットを閉じます。

このトピックでは、すべての Windows コンピューターで使用可能な Echo サービスと Quote of the Day サービスを使用します。簡易 TCP/IP サービスは、すべてのバージョンの Windows で使用可能な機能です。この機能は、次のサービスを提供します。Character GeneratorDaytimeDiscardEcho、および Quote of the Day。それぞれのサービスは TCP 経由でアクセス可能で、通信に使用する既定のポートがそれぞれに割り当てられています。既定のサービスとポートのマッピングは次のとおりです。

サービス名

説明

ポート番号

Echo

このサーバー ポートで受信したすべてのメッセージのデータをエコー バックします。Echo は、ネットワークのデバッグおよび監視ツールとして使用できます。

7

Quote of the Day

メッセージで 1 行または複数行のテキストとして引用を返します。引用は、%SYSTEMROOT%\System32\Drivers\Etc\Quotes ファイルからランダムに取得されます。サンプルの引用ファイルは、簡易 TCP/IP サービスと共にインストールされます。このファイルがない場合、引用サービスは失敗します。

17

Daytime

曜日、月、日、年、現在の時刻 (hh:mm:ss 形式)、およびタイム ゾーン情報を含むメッセージを返します。一部のプログラムでは、これらのサービスの出力を使用して、システム クロックの時刻や異なるホスト上での差異のデバッグや監視を行うこともできます。

13

Character Generator

印刷可能な 95 個の ASCII 文字のセットで構成されたデータを送信します。ライン プリンターのテストとトラブルシューティングを行うためのデバッグ ツールとして役立ちます。

19

Discard

応答や確認応答を返すことなく、このポートで受信したすべてのメッセージを破棄します。ネットワークのセットアップおよび構成時に、TCP/IP テスト メッセージの受信やルーティングのための null ポートとして使用したり、場合によっては、プログラムでメッセージ破棄機能として使用したりすることもできます。

9

コンピューター上で簡易 TCP/IP サービスを有効にするには

  1. コントロール パネルの [プログラムと機能] を開きます。

  2. [Windows の機能の有効化または無効化] をクリックします。

  3. [Windows の機能] ダイアログで、[簡易 TCP/IP サービス] チェック ボックスをオンにしてこの機能を有効にし、[OK] をクリックします。

    重要:重要:

    この手順を実行するには、ローカル コンピューター上の Administrators グループまたは Network Configuration Operators グループのメンバーである必要があります。

  4. 使用しているコンピューター上のサービス一覧で、[簡易 TCP/IP サービス] というサービスが開始されていることを確認します。開始されていない場合は、サービスを手動で開始します。サービスの開始の詳細については、「サービス開始方法の構成」を参照してください。

ここでは、このトピックで作成したアプリを実行する方法について説明します。

TCP ソケット クライアント アプリを実行するには

  1. デバイスで、[デバッグ] メニューの [デバッグ開始] をクリックしてアプリを実行します。

  2. Echo 機能を試すには:

    1. [ホスト名] フィールドにホスト名を追加します。

    2. [エコーするテキスト] フィールドに、送信するテキストを追加します。

    3. [エコー] をクリックします。

    出力ウィンドウに、端末上のクライアントとサーバーの間での通信のラウンドトリップと、エラーが発生した場合はそのエラーが表示されます。

  3. Quote of the Day 機能を試すには:

    1. [ホスト名] フィールドにホスト名を追加します。

    2. [引用の取得] をクリックします。

    出力ウィンドウに、端末上のクライアントとサーバーの間での通信のラウンドトリップと、エラーが発生した場合はそのエラーが表示されます。

表示: