2017/01/25

[C#]UDP Socket Send&Receive

在這裡寫一個C#用UDP來接收跟傳送Socket的範例。
主要分為兩部分來寫,分別是Receive and Send Socket

如果懶得寫class,可以直接下載這三個檔案來用

RecieveDataEventArgs.cs
UdpSocketHoster.cs
UdpSocketSender.cs


新增一個WPF的專案,專案名稱命名為AppicationName。


Receive  Socket

加入ReceiveDataEventArgs,準備給UdpSocketHoster使用。


ReceiveDataEventArgs.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ApplicationName
{
    public class ReceiveDataEventArgs : EventArgs
    {
        #region Fields (1) 

        private object mData;

        #endregion Fields 

        #region Constructors (1) 

        public ReceiveDataEventArgs(object data)
        {
            this.mData = data;
        }

        #endregion Constructors 

        #region Properties (1) 

        public object Data
        {
            get
            {
                return mData;
            }
        }

        #endregion Properties 
    }
}

在專案中另外再加入UdpSocketHoster,用來接收Socket。

UdpSocketHoster.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

namespace ApplicationName
{
    public class UdpSocketHoster
    {
        #region Fields (3) 

        private Thread mListenThread;
        private int mReceiverBuffer = 65536;
        private Socket mSocket;

        #endregion Fields 

        #region Properties (3) 

        public string Ip
        {
            get;
            set;
        }

        public int Port
        {
            get;
            set;
        }

        public int ReceiverBuffer
        {
            get { return mReceiverBuffer; }
            set { mReceiverBuffer = value; }
        }

        #endregion Properties 

        #region Delegates and Events (3) 

        // Events (3) 

        public event EventHandler ReceivedData;

        public event EventHandler StartListening;

        public event EventHandler StopListening;

        #endregion Delegates and Events 

        #region Methods (4) 

        // Public Methods (3) 

        public void Start()
        {
            if (StartListening != null)
            {
                StartListening(this, new EventArgs());
            }

            mListenThread = new Thread(new ParameterizedThreadStart(startListen));
            mListenThread.Start();
        }

        public void Start(string ip, int port)
        {
            this.Ip = ip;
            this.Port = port;

            Start();
        }

        public void Stop()
        {
            if (StopListening != null)
            {
                StopListening(this, new EventArgs());
            }

            mSocket.Close();
            mListenThread.Abort();
        }
        // Private Methods (1) 

        private void startListen(object sender)
        {
            //Setting Endpoint
            IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, Port);
            mSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

            //Binding Endpoint
            mSocket.Bind(endpoint);

            //Getting Client Ip
            IPEndPoint clientEndpoint = new IPEndPoint(IPAddress.Any, 0);
            EndPoint Remote = (EndPoint)(clientEndpoint);
           
            //Start loop for receiving data
            while (true)
            {
                try
                {
                    int recv;
                    byte[] receivePackage = new byte[mReceiverBuffer];

                    //Receive data from client
                    recv = mSocket.ReceiveFrom(receivePackage, ref Remote);

                    //remove empty byte
                    byte[] cropped = new byte[recv];
                    Array.Copy(receivePackage, 0, cropped, 0, recv);

                    String str = System.Text.Encoding.UTF8.GetString(cropped, 0, cropped.Length);

                    ////Deserialize data
                    //BinaryFormatter bf = new BinaryFormatter();
                    //MemoryStream stream = new MemoryStream(receivePackage);
                    //object data = bf.Deserialize(stream);

                    if (ReceivedData != null)
                    {
                        ReceivedData(this, new ReceiveDataEventArgs(str));
                    }
                }
                catch (Exception ex)
                {
                    throw;
                }
            }
        }

        #endregion Methods 
    }
}

先準備好這兩個class之後就可以開始在MainWindow裡面用了

MainWindow.cs
public partial class MainWindow : Window
    {        
        UdpSocketHoster myhoster = new UdpSocketHoster();

        public MainWindow()
        {
            InitializeComponent();
            
            // initial socket hoster
            initSocket();

        }
        public void initSocket()
        {
            myhoster = new UdpSocketHoster();
            myhoster.ReceivedData += (o, e) => ReceiveData8000(e.Data.ToString());
            myhoster.StartListening += (o, e) => Console.WriteLine("Start Hosting...");
            myhoster.StopListening += (o, e) => Console.WriteLine("Stop Hosting...");
            myhoster.Start("127.0.0.1", 8000);
        }

        // receive _data string
        public void ReceiveData8000(String _data)
        {
            Dispatcher.BeginInvoke(new Action(() =>
            {
                label_socket.Content = _data;
                ColorChange(_data);

            }));
        }

        // stop host when exit
        private void Window_main_Closed(object sender, EventArgs e)
        {
            myhoster.Stop();
        }
    }


1. myhoster.Start("127.0.0.1", 8000)就是設定host的IP位置跟port。ps. 本機的IP是127.0.0.1
2. _data則是收到socket的字串資料,收到_data之後可以做後面的處理。
3. 最後記得在關掉程式的時候,也要把host停掉,不然host會在背後一直跑。


Send Socket

在專案中加入UdpSocketSender


UdpSocketSender.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;

namespace ApplicationName
{
    public class UdpSocketSender
    {
        #region Fields (1) 

        private int mPackageBuffer = 1024;

        #endregion Fields 

        #region Constructors (1) 

        public UdpSocketSender(string ip, int port)
        {
            this.Ip = ip;
            this.Port = port;
        }

        #endregion Constructors 

        #region Properties (3) 

        public string Ip { get; set; }

        public int PackageBuffer
        {
            get { return mPackageBuffer; }
            set { mPackageBuffer = value; }
        }

        public int Port { get; set; }

        #endregion Properties 

        #region Methods (1) 

        // Public Methods (1) 

        public void Send(string data)
        {
            //Setting Server Endpoint
            IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(Ip), Port);
            Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            server.EnableBroadcast = true;

            //Serialize Data
            byte[] package = new byte[mPackageBuffer];
            BinaryFormatter bf = new BinaryFormatter();
            MemoryStream stream = new MemoryStream();
            bf.Serialize(stream, data);
            package = stream.ToArray();

            //Send Data

            byte[] b = System.Text.Encoding.UTF8.GetBytes(data);

            server.SendTo(b, b.Length, SocketFlags.None, endPoint);
        }

        #endregion Methods 
    }
}

接著只要在MainWindow.cs裡面加入宣告
UdpSocketSender mysender = new UdpSocketSender("127.0.0.1", 8000);
準備一個mysender負責對IP:127.0.0.1(本機) port:8000傳送資料。
之後就可以直接用mysend來傳送字串"Test"。
mysender.Send("Test");

最後放上完整的MainWindow程式碼(包括receive跟send功能)
    public partial class MainWindow : Window
    {        
        UdpSocketHoster myhoster = new UdpSocketHoster();
        UdpSocketSender mysender = new UdpSocketSender("127.0.0.1", 8000);

        public MainWindow()
        {
            InitializeComponent();
            
            // initial socket hoster
            initSocket();
   
            // send socket
            mysender.Send("Test");
        }
        public void initSocket()
        {
            myhoster = new UdpSocketHoster();
            myhoster.ReceivedData += (o, e) => ReceiveData8000(e.Data.ToString());
            myhoster.StartListening += (o, e) => Console.WriteLine("Start Hosting...");
            myhoster.StopListening += (o, e) => Console.WriteLine("Stop Hosting...");
            myhoster.Start("127.0.0.1", 8000);
        }

        // receive _data string
        public void ReceiveData8000(String _data)
        {
            Dispatcher.BeginInvoke(new Action(() =>
            {
                label_socket.Content = _data;
                ColorChange(_data);

            }));
        }

        // stop host when exit
        private void Window_main_Closed(object sender, EventArgs e)
        {
            myhoster.Stop();
        }
    }


沒有留言:

張貼留言