13,226
回編集
| 29行目: | 29行目: | ||
<br><br> | <br><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.Net.Sockets; | using System.Net.Sockets; | ||
using System.Threading.Tasks; | |||
class | class AsyncTcpClientSender | ||
{ | { | ||
static | 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( | using (TcpClient client = new TcpClient()) | ||
{ | { | ||
// サーバへ接続 | |||
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. | |||
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}"); | ||
} | } | ||
} | } | ||
} | } | ||
catch (SocketException e) | catch (SocketException e) | ||
{ | { | ||
Console.WriteLine($"SocketException: {e.Message}"); | Console.WriteLine($"SocketException: {e.Message}"); | ||
} | } | ||
catch ( | catch (TimeoutException e) | ||
{ | { | ||
Console.WriteLine($" | Console.WriteLine($"TimeoutException: {e.Message}"); | ||
} | } | ||
catch (Exception e) | catch (Exception e) | ||
{ | { | ||
Console.WriteLine($" | Console.WriteLine($"予期せぬエラーが発生: {e.Message}"); | ||
} | } | ||
} | } | ||