Last active
February 12, 2017 13:51
-
-
Save ichiroku11/75b9166702e07c5945f8ce91b5670a09 to your computer and use it in GitHub Desktop.
.NETでUDP(UdpClient)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Net; | |
using System.Net.Sockets; | |
using System.Runtime.Serialization; | |
using System.Runtime.Serialization.Formatters.Binary; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace Udp.ConsoleApp { | |
// オブジェクトとバイト配列の変換 | |
public class ObjectConverter<TObject> { | |
private readonly IFormatter _formatter; | |
public ObjectConverter(IFormatter formatter = null) { | |
_formatter = formatter ?? new BinaryFormatter(); | |
} | |
// オブジェクト=>バイト配列 | |
public byte[] ToByteArray(TObject obj) { | |
using (var stream = new MemoryStream()) { | |
_formatter.Serialize(stream, obj); | |
return stream.ToArray(); | |
} | |
} | |
// バイト配列=>オブジェクト | |
public TObject FromByteArray(byte[] bytes) { | |
using (var stream = new MemoryStream(bytes)) { | |
return (TObject)_formatter.Deserialize(stream); | |
} | |
} | |
} | |
// クライアント | |
public class Client<TRequest, TResponse> { | |
// 送信先のエンドポイント | |
private readonly IPEndPoint _endpoint; | |
public Client(IPEndPoint endpoint) { | |
_endpoint = endpoint; | |
} | |
// クライアントを実行する | |
// リクエストを送信してレスポンスを受信する | |
public async Task<TResponse> SendAsync(TRequest request) { | |
// UdpClientを作成するときにはエンドポイントを指定しない | |
using (var client = new UdpClient()) { | |
// 1. リクエストを送信 | |
// (送信先のエンドポイントを指定して) | |
Console.WriteLine($"Client send {nameof(request)}: {request}"); | |
var requestBytes = new ObjectConverter<TRequest>().ToByteArray(request); | |
await client.SendAsync(requestBytes, requestBytes.Length, _endpoint); | |
// 2. レスポンスを受信 | |
var result = await client.ReceiveAsync(); | |
// ここで受信した結果のリモートエンドポイントが送信先かをチェックした方がいい気がする | |
var responseBytes = result.Buffer; | |
var response = new ObjectConverter<TResponse>().FromByteArray(responseBytes); | |
Console.WriteLine($"Client receive {nameof(response)}: {response}"); | |
return response; | |
} | |
} | |
} | |
// サーバ | |
public class Server<TRequest, TResponse> { | |
// リクエストを受信するエンドポイント | |
private readonly IPEndPoint _endpoint; | |
public Server(IPEndPoint endpoint) { | |
_endpoint = endpoint; | |
} | |
// サーバを実行する | |
public async Task RunAsync(Func<TRequest, TResponse> processor) { | |
// リクエストを受信するエンドポイントを指定してUdpClientを作成 | |
using (var client = new UdpClient(_endpoint)) { | |
while (true) { | |
// 1. リクエストを受信 | |
var result = await client.ReceiveAsync(); | |
var requestBytes = result.Buffer; | |
var request = new ObjectConverter<TRequest>().FromByteArray(requestBytes); | |
Console.WriteLine($"Server receive {nameof(request)}: {request}"); | |
var sender = Task.Run(async () => { | |
// 2. リクエストからレスポンスを作成 | |
var response = processor(request); | |
// 3. リクエストの送信元にレスポンスを送信 | |
Console.WriteLine($"Server send {nameof(response)}: {response}"); | |
var responseBytes = new ObjectConverter<TResponse>().ToByteArray(response); | |
await client.SendAsync(responseBytes, responseBytes.Length, result.RemoteEndPoint); | |
}); | |
// Taskの管理やエラー処理は省略 | |
} | |
} | |
} | |
} | |
class Program { | |
// サーバの作成 | |
public static Server<string, string> Server(IPEndPoint endpoint) | |
=> new Server<string, string>(endpoint); | |
// クライアントの作成 | |
public static Client<string, string> Client(IPEndPoint endpoint) | |
=> new Client<string, string>(endpoint); | |
// 文字列を並びを反対にする | |
private static string Reverse(string original) | |
=> new string(original.Reverse().ToArray()); | |
static void Main(string[] args) { | |
var endpoint = new IPEndPoint(IPAddress.Loopback, 54321); | |
// サーバを実行 | |
var server = Task.Run(() => Server(endpoint).RunAsync(Reverse)); | |
// クライアントを実行 | |
Task.WaitAll( | |
Client(endpoint).SendAsync("あいうえお"), | |
Client(endpoint).SendAsync("かきくけこ")); | |
// サーバのTaskをきれいに終了するにはどうしたらいいのか... | |
} | |
} | |
// 実行結果 | |
/* | |
Client send request: あいうえお | |
Server receive request: あいうえお | |
Client send request: かきくけこ | |
Server receive request: かきくけこ | |
Server send response: おえういあ | |
Server send response: こけくきか | |
Client receive response: おえういあ | |
Client receive response: こけくきか | |
*/ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment