ソケットを使用してリモート デバイスと通信するには、そのソケットをプロトコルとネットワーク アドレス情報で初期化する必要があります。
Socket クラスのコンストラクターには、ソケットが接続に使用するアドレス ファミリ、ソケットの種類、プロトコルの種類を指定するパラメーターがあります。 クライアント ソケットをサーバー ソケットに接続する場合、クライアントは IPEndPoint
オブジェクトを使用してサーバーのネットワーク アドレスを指定します。
IP エンドポイントを作成する
System.Net.Sockets を使うときは、ネットワーク エンドポイントを IPEndPoint オブジェクトとして表します。
IPEndPoint
は、IPAddress とそれに対応するポート番号を使って構築されます。
Socket を使って会話を始める前に、アプリとリモートの通信先との間にデータ パイプを作成します。
TCP/IP はネットワーク アドレスとサービス ポート番号を使用して、サービスを一意に識別しています。 ネットワーク アドレスは、特定のネットワーク通信先を示します。ポート番号は、そのデバイス上の接続先である特定のサービスを示します。 ネットワーク アドレスとサービス ポートの組み合わせはエンドポイントと呼ばれ、.NET では EndPoint クラスによって表されます。
EndPoint
の子孫は、サポートされるアドレス ファミリごとに定義されます。IP アドレス ファミリの場合、クラスは IPEndPoint です。
Dns クラスは、TCP/IP インターネット サービスを使うアプリにドメインネーム サービスを提供します。
GetHostEntryAsync メソッドは、DNS サーバーのクエリを実行して、ユーザー フレンドリなドメイン名 ("host.contoso.com" など) を数値のインターネット アドレス (192.168.1.1
など) にマップします。
GetHostEntryAsync
は、要求した名前のアドレスとエイリアスの一覧を待機した後に含む Task<IPHostEntry>
を返します。 ほとんどの場合、AddressList 配列で返された最初のアドレスを使用できます。 次のコードは、サーバー IPAddress の IP アドレスを含む host.contoso.com
を取得します。
IPHostEntry ipHostInfo = await Dns.GetHostEntryAsync("host.contoso.com");
IPAddress ipAddress = ipHostInfo.AddressList[0];
ヒント
手動テストとデバッグには、通常は、GetHostEntryAsync 値の結果のホスト名と共に Dns.GetHostName() メソッドを使って、localhost 名を IP アドレスに解決できます。 次のコード スニペットを考えてみます。
var hostName = Dns.GetHostName();
IPHostEntry localhost = await Dns.GetHostEntryAsync(hostName);
// This is the IP address of the local machine
IPAddress localIpAddress = localhost.AddressList[0];
Internet Assigned Numbers Authority (IANA) により、一般的なサービス用のポート番号が定義されています。 詳細については、IANA: 「Service Name and Transport Protocol Port Number Registry (サービス名とトランスポート プロトコル ポート番号の登録)」を参照してください。 他のサービスが、1,024 から 65,535 の範囲内でポート番号を登録している可能性があります。 次のコードは、host.contoso.com
の IP アドレスとポート番号を組み合わせて、接続のためのリモート エンドポイントを作成します。
IPEndPoint ipEndPoint = new(ipAddress, 11_000);
リモート デバイスのアドレスを決定し、接続に使用するポートを選択すると、アプリはそのリモート デバイスとの接続を確立できます。
Socket
クライアントを作成する
endPoint
オブジェクトを作成したら、サーバーに接続するクライアント ソケットを作成します。 ソケットが接続されると、サーバー ソケット接続からデータを送受信できます。
using Socket client = new(
ipEndPoint.AddressFamily,
SocketType.Stream,
ProtocolType.Tcp);
await client.ConnectAsync(ipEndPoint);
while (true)
{
// Send message.
var message = "Hi friends 👋!<|EOM|>";
var messageBytes = Encoding.UTF8.GetBytes(message);
_ = await client.SendAsync(messageBytes, SocketFlags.None);
Console.WriteLine($"Socket client sent message: \"{message}\"");
// Receive ack.
var buffer = new byte[1_024];
var received = await client.ReceiveAsync(buffer, SocketFlags.None);
var response = Encoding.UTF8.GetString(buffer, 0, received);
if (response == "<|ACK|>")
{
Console.WriteLine(
$"Socket client received acknowledgment: \"{response}\"");
break;
}
// Sample output:
// Socket client sent message: "Hi friends 👋!<|EOM|>"
// Socket client received acknowledgment: "<|ACK|>"
}
client.Shutdown(SocketShutdown.Both);
前述の C# コードでは、次のことが行われます。
特定の
endPoint
インスタンス アドレス ファミリ、SocketType.Stream、およびProtocolType.Tcpを使用して、新しいSocket
オブジェクトをインスタンス化します。endPoint
インスタンスを引数として使用して、Socket.ConnectAsync メソッドを呼び出します。while
ループの場合:- Socket.SendAsyncを使用してメッセージをエンコードし、サーバーに送信します。
- 送信されたメッセージをコンソールに書き込みます。
- Socket.ReceiveAsyncを使用して、サーバーからデータを受信するバッファーを初期化します。
-
response
が受信確認である場合、コンソールに書き込まれ、ループが終了します。
最後に、
client
ソケット呼び出し Socket.Shutdown 指定された SocketShutdown.Bothによって、送信操作と受信操作の両方がシャットダウンされます。
Socket
サーバーを作成する
サーバー ソケットを作成するには、 endPoint
オブジェクトは任意の IP アドレスで受信接続をリッスンできますが、ポート番号を指定する必要があります。 ソケットが作成されると、サーバーは受信接続を受け入れ、クライアントと通信できます。
using Socket listener = new(
ipEndPoint.AddressFamily,
SocketType.Stream,
ProtocolType.Tcp);
listener.Bind(ipEndPoint);
listener.Listen(100);
var handler = await listener.AcceptAsync();
while (true)
{
// Receive message.
var buffer = new byte[1_024];
var received = await handler.ReceiveAsync(buffer, SocketFlags.None);
var response = Encoding.UTF8.GetString(buffer, 0, received);
var eom = "<|EOM|>";
if (response.IndexOf(eom) > -1 /* is end of message */)
{
Console.WriteLine(
$"Socket server received message: \"{response.Replace(eom, "")}\"");
var ackMessage = "<|ACK|>";
var echoBytes = Encoding.UTF8.GetBytes(ackMessage);
await handler.SendAsync(echoBytes, 0);
Console.WriteLine(
$"Socket server sent acknowledgment: \"{ackMessage}\"");
break;
}
// Sample output:
// Socket server received message: "Hi friends 👋!"
// Socket server sent acknowledgment: "<|ACK|>"
}
前述の C# コードでは、次のことが行われます。
特定の
endPoint
インスタンス アドレス ファミリ、SocketType.Stream、およびProtocolType.Tcpを使用して、新しいSocket
オブジェクトをインスタンス化します。listener
は、ソケットをネットワーク アドレスに関連付ける引数として、endPoint
インスタンスを使用してSocket.Bind メソッドを呼び出します。Socket.Listen() メソッドは、着信接続をリッスンするために呼び出されます。
listener
は、Socket.AcceptAsync メソッドを呼び出して、handler
ソケットで受信接続を受け入れます。while
ループの場合:- Socket.ReceiveAsyncを呼び出して、クライアントからデータを受信します。
- データが受信されると、デコードされ、コンソールに書き込まれます。
-
response
メッセージが<|EOM|>
で終わると、Socket.SendAsyncを使用して受信確認がクライアントに送信されます。
サンプル クライアントとサーバーを実行する
最初にサーバー アプリケーションを起動し、次にクライアント アプリケーションを起動します。
dotnet run --project socket-server
Socket server starting...
Found: 172.23.64.1 available on port 9000.
Socket server received message: "Hi friends 👋!"
Socket server sent acknowledgment: "<|ACK|>"
Press ENTER to continue...
クライアント アプリケーションはサーバーにメッセージを送信し、サーバーは受信確認で応答します。
dotnet run --project socket-client
Socket client starting...
Found: 172.23.64.1 available on port 9000.
Socket client sent message: "Hi friends 👋!<|EOM|>"
Socket client received acknowledgment: "<|ACK|>"
Press ENTER to continue...
こちらも参照ください
.NET