「C Sharpとネットワーク - TCP Client」の版間の差分

ナビゲーションに移動 検索に移動
29行目: 29行目:
<br><br>
<br><br>


== サンプルコード ==
== クライアント : 送信 ==
以下の例では、TcpClientクラスを使用して、サーバに接続およびメッセージを送信して応答を受信している。<br>
以下の例では、TcpClientクラスを使用して、非同期でサーバに接続およびメッセージを送信している。<br>
また、タイムアウトが発生した場合の再試行処理や高度なエラー処理等も追加することを推奨する。<br>
<br>
<code>NetworkStream</code>クラスの<code>ReadTimeout</code>や<code>WriteTimeout</code>プロパティを非同期処理と組み合わせることは非推奨である。<br>
非同期操作でタイムアウトを実装する場合、<code>Task.WhenAny</code>と<code>Task.Delay</code>を組み合わせる方法が効果的である。<br>
<br>
* 互換性の問題
*: <code>ReadTimeout</code>プロパティおよび<code>WriteTimeout</code>プロパティは、同期メソッド (Read, Write) に対してのみ有効である。
*: 非同期メソッド (ReadAsync, WriteAsync) には影響しない。
*: <br>
* 非同期操作との不適合
*: 非同期操作は本質的にタイムアウトの概念と相容れない。
*: 非同期メソッドは完了するまで制御を返さないため、タイムアウトを設定しても期待通りに動作しない。
<br>
<br>
  <syntaxhighlight lang="c#">
  <syntaxhighlight lang="c#">
  using System;
  using System;
  using System.Text;
  using System.Text;
using System.IO;
  using System.Net.Sockets;
  using System.Net.Sockets;
using System.Threading.Tasks;
   
   
  class TcpClientExample
  class AsyncTcpClientSender
  {
  {
     static void Main()
     static async Task Main(string[] args)
     {
     {
       string server = "<ホスト名またはIPアドレス>";  // サーバのアドレス
       string server = "<ホスト名またはIPアドレス>";  // サーバのアドレス
       int port     = <ポート番号>;               // ポート番号
       int port = <ポート番号>;                     // ポート番号
      int timeoutMilliseconds = 5000;            // タイムアウト (ミリ秒)
   
   
       try
       try
       {
       {
           using (TcpClient client = new TcpClient(server, port))
           using (TcpClient client = new TcpClient())
           {
           {
             Console.WriteLine("サーバに接続");
             // サーバへ接続
            var connectTask = client.ConnectAsync(server, port);
            // サーバへの接続が確立するまで待機
            if (await Task.WhenAny(connectTask, Task.Delay(timeoutMilliseconds)) != connectTask)
            {  // タイムアウトが発生した場合
                throw new TimeoutException("エラー: サーバへの接続がタイムアウト");
            }
   
   
             using (NetworkStream stream = client.GetStream())
             using (NetworkStream stream = client.GetStream())
             {
             { // サーバへメッセージを送信
                // サーバにメッセージを送信
                 string message = "Hello, Server";
                 string message = "Hello, Server";
                 byte[] data = Encoding.UTF8.GetBytes(message);
                 byte[] data = Encoding.UTF8.GetBytes(message);
                 stream.Write(data, 0, data.Length);
                 var sendTask = stream.WriteAsync(data, 0, data.Length);
                if (await Task.WhenAny(sendTask, Task.Delay(timeoutMilliseconds)) != sendTask)
                {
                  throw new TimeoutException("エラー: メッセージの送信がタイムアウト");
                }
                 Console.WriteLine($"送信メッセージ: {message}");
                 Console.WriteLine($"送信メッセージ: {message}");
                // サーバーからの応答を受信
                data = new byte[256];
                int bytes = stream.Read(data, 0, data.Length);
                string responseData = Encoding.UTF8.GetString(data, 0, bytes);
                Console.WriteLine($"受信メッセージ: {responseData}");
             }
             }
           }
           }
      }
      catch (ArgumentNullException e)
      {  // 無効な引数が渡された場合
          Console.WriteLine($"ArgumentNullException: {e.Message}");
       }
       }
       catch (SocketException e)
       catch (SocketException e)
       { // ネットワーク関連のエラーが発生した場合
       {
           Console.WriteLine($"SocketException: {e.Message}");
           Console.WriteLine($"SocketException: {e.Message}");
       }
       }
       catch (IOException e)
       catch (TimeoutException e)
       { // ストリームの読み書き中にエラーが発生した場合
       {
           Console.WriteLine($"IOException: {e.Message}");
           Console.WriteLine($"TimeoutException: {e.Message}");
       }
       }
       catch (Exception e)
       catch (Exception e)
       { // その他の予期せぬエラーが発生した場合
       {
           Console.WriteLine($"予期せぬエラーが発生しました: {e.Message}");
           Console.WriteLine($"予期せぬエラーが発生: {e.Message}");
       }
       }
     }
     }

案内メニュー