C#でのUDP通信の簡易実装

はじめに

UDP通信をC#で実装する方法は2つあります。1つは低レベルのSocketクラスを直接使う方法、もう1つはより高レベルなUdpClientクラスを利用する方法です。後者のほうがコード量が少なく簡単です。

以下、それぞれの実装例を示します。

方法1:Socketクラスをラップした簡易ライブラリ

送信側(クライアント)

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace UdpSimple
{
    // UDP送信をラップするクラス
    public class UdpSender : IDisposable
    {
        private Socket socket;

        public UdpSender()
        {
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        }

        public void Send(string message, string ip, int port)
        {
            if (string.IsNullOrEmpty(message))
            {
                Console.WriteLine("メッセージが空です");
                return;
            }

            byte[] bytes = Encoding.UTF8.GetBytes(message);
            EndPoint remote = new IPEndPoint(IPAddress.Parse(ip), port);
            socket.SendTo(bytes, remote);
        }

        public void Dispose()
        {
            socket?.Close();
        }
    }

    class Program
    {
        static void Main()
        {
            Console.WriteLine("送信するメッセージを入力してください");
            using (var sender = new UdpSender())
            {
                while (true)
                {
                    string msg = Console.ReadLine();
                    if (msg == "exit") break;
                    sender.Send(msg, "192.168.1.104", 3333);
                    Console.WriteLine("送信しました");
                }
            }
        }
    }
}

受信側(サーバー)

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace UdpSimple
{
    public class UdpReceiver : IDisposable
    {
        private Socket socket;
        private CancellationTokenSource cts;

        public UdpReceiver(string localIp, int localPort)
        {
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            socket.Bind(new IPEndPoint(IPAddress.Parse(localIp), localPort));
        }

        public void StartListening()
        {
            cts = new CancellationTokenSource();
            Task.Run(() => ReceiveLoop(cts.Token));
        }

        private void ReceiveLoop(CancellationToken token)
        {
            byte[] buffer = new byte[1024];
            EndPoint remote = new IPEndPoint(IPAddress.Any, 0);

            while (!token.IsCancellationRequested)
            {
                try
                {
                    int len = socket.ReceiveFrom(buffer, ref remote);
                    string msg = Encoding.UTF8.GetString(buffer, 0, len);
                    var clientEP = (IPEndPoint)remote;
                    Console.WriteLine($"受信元: {clientEP.Address}:{clientEP.Port} → 内容: {msg}");
                }
                catch (SocketException ex)
                {
                    Console.WriteLine($"受信エラー: {ex.Message}");
                }
            }
        }

        public void Stop()
        {
            cts?.Cancel();
        }

        public void Dispose()
        {
            Stop();
            socket?.Close();
            cts?.Dispose();
        }
    }

    class Program
    {
        static void Main()
        {
            using (var receiver = new UdpReceiver("192.168.1.104", 3333))
            {
                receiver.StartListening();
                Console.WriteLine("受信を開始しました。Enterキーで終了");
                Console.ReadLine();
            }
        }
    }
}

方法2:UdpClientクラスを使った簡易実装

受信側(サーバー)

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace UdpClientSample
{
    class Program
    {
        static void Main()
        {
            using (var client = new UdpClient(new IPEndPoint(IPAddress.Parse("192.168.1.104"), 3333)))
            {
                IPEndPoint remote = new IPEndPoint(IPAddress.Any, 0);
                Console.WriteLine("受信待機中…");
                while (true)
                {
                    byte[] data = client.Receive(ref remote);
                    string msg = Encoding.UTF8.GetString(data);
                    Console.WriteLine($"送信元: {remote.Address}:{remote.Port} → メッセージ: {msg}");
                }
            }
        }
    }
}

送信側(クライアント)

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace UdpClientSample
{
    class Program
    {
        static void Main()
        {
            using (var client = new UdpClient())
            {
                Console.WriteLine("送信するメッセージを入力してください");
                while (true)
                {
                    string msg = Console.ReadLine();
                    if (msg == "exit") break;
                    byte[] data = Encoding.UTF8.GetBytes(msg);
                    client.Send(data, data.Length, new IPEndPoint(IPAddress.Parse("192.168.1.104"), 3333));
                }
            }
        }
    }
}

補足

上記のコードでは、ローカルIPアドレスを192.168.1.104と仮定しています。実際の環境に合わせて変更してください。また、UdpClientを使用する場合は、明示的なクローズ処理をusing文で自動化しています。

タグ: C# udp ソケット通信 UdpClient

7月6日 23:49 投稿