C#

【C#】TcpClientでクライアントの通信処理を作成

TCP/IP通信は確実にデータの送受信ができるので通信品質が高く、現在でも使用されている通信手段の1つとして使用されています。

C#でTCP/IP通信を非同期処理でプログラムを実装する方法をこの記事にまとめていますので、参考にしてみてください。

環境

OSWindows10
IDEVisual Studio 2019
フレームワーク.NET Core3.1
UIフレームワークWPFアプリ

TCP/IPの通信イメージ

まずTCP/IP通信は、サービスや機能を利用するクライアントとサービスや機能を提供するサーバーが相互に接続しあってデータの送受信を行います。

C#ではクライアントとサーバーのプログラミングを簡単に実装できるように、Socketクラスをベースとした、TcpClientクラスとTcpListenerクラスが用意されています。

この2つのクラスを利用した場合の通信イメージを理解しておくことで、プログラミングがスムーズに出来ると思いますので、下図の通信手順をみてみましょう。

  1. サーバー側はTcpListenerクラスで接続を開始して、クライアントからの要求を待ち受けします。
  2. クライアント側はTcpClientクラスで接続要求をし、サーバーに接続します。
  3. サーバーはクライアント側からの接続要求を受け付けると、TcpClientオブジェクトを作成して通信を確立します。
  4. 通信確立後、クライアントからリクエストを送信し、サーバーはリクエストを受信します。
  5. サーバーからレスポンスを送信し、クライアントはレスポンスを受信します。
  6. 最後にサーバーとクライアントのTcpClientの接続を閉じます。

今回のサンプルコードではクライアントとサーバー間で接続をして、クライアントから「Hello」を受信したら、「OK」を送信するプログラムを作成します。通信には非同期処理を使用します。

クライアント側の処理

クライアント側の処理を行う為に2つの関数を用意します。上図のフローチャート(通信処理の流れ)と比較しながら関数の役割を確認してみてください。

関数役割
StartClient接続先のエンドポイント(IPアドレスとポート)を指定する。サーバーへリクエストを送信し、サーバーからの応答を受信する。

サンプルソースコード

「tcpclient.cs」という新しい項目(ファイル)を作成して、プロジェクトに追加します。

ソケット関連で使用する名前空間 System.Net.Sockets を参照するために、usingディレクティブを用いてコードの先頭に記述します。
using System.Net.Sockets;

StartClient関数

先ほど作成したtcpclient.csに記述するコードは以下になります。
public async Task<string> StartClient(string ipaddress, int port, string request)
{
    var buffer = new byte[1024];
    var response = "";

    // サーバーへ接続
    try
    {
        // クライアント作成
        using (var tcpclient = new TcpClient())
        {
            // 送受信タイムアウト設定
            tcpclient.SendTimeout = 1000;
            tcpclient.ReceiveTimeout = 1000;

            // サーバーへ接続開始
            await tcpclient.ConnectAsync(ipaddress, port);
            Debug.WriteLine("サーバーと通信確立");
            using (var stream = tcpclient.GetStream())
            {
                // サーバーへリクエストを送信
                buffer = System.Text.Encoding.ASCII.GetBytes(request);
                await stream.WriteAsync(buffer);
                Debug.WriteLine($"サーバーへ[{request}]を送信");

                // サーバーからレスポンスを受信
                var length = await stream.ReadAsync(buffer, 0, buffer.Length);
                response = System.Text.Encoding.ASCII.GetString(buffer, 0, length);
                Debug.WriteLine($"サーバーから[{response}]を受信");
            }
        }
    }
    catch (Exception ex)
    {
        Debug.WriteLine(ex.ToString());
    }

    return response;
}
new演算子を使用してTcpClientのインスタンスを作成します。ConnectAsync でアドレスとポート番号を指定して、非同期でサーバーへ接続します。接続が確立されるまで次の処理は実行されず待機されます。実際に使用する際はタイムアウトの処理を記述することになります。
【C#】TcpClientのConnectのタイムアウト設定C#でTcpClientを使ってConnectした場合、デフォルトの設定ではタイムアウトするのがとても遅いです。そこで接続タイムアウトの時間を任意の値に設定する方法を紹介していますので、参考にしてみてください。...

サーバーとデータの送受信を行う為に、ネットワークストリームの情報を GetStream 取得します。サーバーへリクエストを送信する際はバイト型の配列にし、 WriteAsync で非同期にて送信をします。リクエストを送信すると、サーバーからレスポンスがくるのでReadAsyncで受信をします。バイト型の配列で受信データが返ってくるのでアスキーコードに変換をします。

最後にTcpClientを閉じれば処理は完了です。

サンプル使用例

上記で説明したサンプルソースコードを使用して、WPFでクライアントのアプリケーションを作成してみます。

IPアドレスとポート番号を入力して、送信開始ボタンをクリックすればサーバーと接続してリクエストを送信します。画面はマテリアルデザインを適用させてオシャレな画面に仕上げました。

マテリアルデザインの適用方法については、以下の記事で詳しく記載しています。
【WPF】Material Designでオシャレな画面デザインに変更する方法WPFでオシャレなUI画面にするならMaterial Design In XAML Toolkitをオススメします。Material DesignとはGoogleが提唱したデザインシステムで、自作のUI画面に簡単に適用できます。Nugetからパッケージをインストールして適用するまでの手順とデモアプリのインストール方法を紹介します。...
XAMLのソースは以下の記述になります。
<Window
    x:Class="TcpClinet.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="TCP/IP (Server)"
    Width="500"
    Height="370"
    WindowStyle="None"
    mc:Ignorable="d">
    <Grid>
        <!--  ヘッダー  -->
        <materialDesign:ColorZone
            Height="50"
            Padding="12"
            Mode="PrimaryMid">
            <DockPanel>
                <materialDesign:PopupBox DockPanel.Dock="Right" PlacementMode="BottomAndAlignRightEdges">
                    <ListBox>
                        <ListBoxItem Content="Close" />
                    </ListBox>
                </materialDesign:PopupBox>
                <StackPanel Orientation="Horizontal">
                    <materialDesign:PackIcon
                        Width="26"
                        Height="26"
                        Kind="AccessPoint" />
                    <TextBlock
                        Margin="16,0,0,0"
                        VerticalAlignment="Center"
                        Text="TCP/IP SAMPLE" />
                </StackPanel>
            </DockPanel>
        </materialDesign:ColorZone>

        <Label
            Margin="15,61,0,0"
            HorizontalAlignment="Left"
            VerticalAlignment="Top"
            Content="TCP/IP通信のクライアント側のサンプル画面です。" />

        <!--  IPアドレス入力欄  -->
        <Label
            x:Name="lblIpaddress"
            Margin="15,99,0,0"
            HorizontalAlignment="Left"
            VerticalAlignment="Top"
            Content="IP アドレス:" />
        <TextBox
            x:Name="txtIpaddress"
            Width="280"
            Margin="90,86,0,0"
            HorizontalAlignment="Left"
            VerticalAlignment="Top"
            materialDesign:HintAssist.Hint="IPアドレスを入力してください。"
            Style="{StaticResource MaterialDesignFloatingHintTextBox}" />

        <!--  ポート番号入力欄  -->
        <Label
            x:Name="lblPort"
            Margin="15,141,0,0"
            HorizontalAlignment="Left"
            VerticalAlignment="Top"
            Content="ポート番号:" />
        <TextBox
            x:Name="txtPort"
            Width="280"
            Margin="90,128,0,0"
            HorizontalAlignment="Left"
            VerticalAlignment="Top"
            materialDesign:HintAssist.Hint="ポート番号を入力してください。"
            Style="{StaticResource MaterialDesignFloatingHintTextBox}" />

        <!--  送信するデータ入力欄  -->
        <Label
            x:Name="lblSendData"
            Margin="15,183,0,0"
            HorizontalAlignment="Left"
            VerticalAlignment="Top"
            Content="送信データ:" />
        <TextBox
            x:Name="txtSendData"
            Width="280"
            Margin="90,170,0,0"
            HorizontalAlignment="Left"
            VerticalAlignment="Top"
            Text="Hello"
            materialDesign:HintAssist.Hint="送信するデータを入力してください。"
            Style="{StaticResource MaterialDesignFloatingHintTextBox}" />

        <!--  送信開始ボタン  -->
        <Button
            x:Name="btnStart"
            Width="90"
            Height="30"
            Margin="0,177,10,0"
            HorizontalAlignment="Right"
            VerticalAlignment="Top"
            Click="BtnStart_Click"
            Content="送信開始"
            Foreground="Black"
            Style="{StaticResource MaterialDesignOutlinedButton}" />

        <!--  ログ出力欄  -->
        <TextBox
            x:Name="txtLog"
            Margin="10,215,10,10"
            AcceptsReturn="True"
            IsEnabled="{Binding ElementName=MaterialDesignOutlinedTextBoxEnabledComboBox}"
            Style="{StaticResource MaterialDesignOutlinedTextBox}"
            TextWrapping="Wrap"
            VerticalScrollBarVisibility="Auto" />
    </Grid>
</Window>
コードは以下の記述になります。
public partial class MainWindow : Window
{
    tcpclient tcp = new tcpclient();

    public MainWindow()
    {
        InitializeComponent();
    }

    private async void btnStart_Click(object sender, RoutedEventArgs e)
    {
        var responce = await tcp.StartClient(txtIpaddress.Text, int.Parse(txtPort.Text), txtSendData.Text);
        MessageBox.Show(responce);
    }
}

動作確認

サーバー側とクライアント側のアプリケーションをそれぞれ起動します。
【C#】TcpListenerでサーバーの通信処理を作成C#でTcpListenerクラスを使って、非同期でTCP通信するプログラム実装方法について記載しています。この記事ではサーバー側の通信サンプルについて解説していますので、参考にしてみてください。...

クライアントアプリにIPアドレスとポート番号を入力してから送信開始ボタンをクリックして、サーバーへ接続要求をしてみましょう。

上図の結果から分かるようにTCP/IP通信でデータの送受信ができていることが確認できました。

まとめ

クライアント側のTCP/IP通信について記載しました。

この記事ではTcpClientクラスで説明しましたが、Soketクラスを使うことでTCP/IP通信することもできますので、興味がある方は以下の記事も読んでみてください。
【C#】ソケット通信(非同期)でクライアントの処理を記述する方法非同期でクライアント側のソケット通信を実装する方法について記載しています。本記事で紹介しているプログラム言語はC#です。ソケット通信について詳しく解説していきますので、参考にして下さい。...

以上、最後まで読んでいただきありがとうございました。

プログラミングを学習したいなら…

プログラミングスキルを身に付けるなら、プログラミングを効率良く学べる
プログラミングスクール」がオススメです。

特にこんな方にオススメ!!
これからエンジニアを目指したい
プログラミングの専門性を高めたい
プログラミングを学んで副業をしたい
エンジニアに転職して年収をアップさせたい

プログラミングを触ったことがない未経験からでも、プログラミングスクールで学習すれば、エンジニアへ就職・転職することも可能です。

あなたの「行動力」と「やる気」で、あなたの人生を大きく変えるチャンスになることでしょう。

プログラミングスクールに興味がある方は是非チェックしてみてください。

> プログラミングを学ぶ <

COMMENT

メールアドレスが公開されることはありません。

CAPTCHA