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


  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6.  
  7. namespace ApplicationName
  8. {
  9. public class ReceiveDataEventArgs : EventArgs
  10. {
  11. #region Fields (1)
  12.  
  13. private object mData;
  14.  
  15. #endregion Fields
  16.  
  17. #region Constructors (1)
  18.  
  19. public ReceiveDataEventArgs(object data)
  20. {
  21. this.mData = data;
  22. }
  23.  
  24. #endregion Constructors
  25.  
  26. #region Properties (1)
  27.  
  28. public object Data
  29. {
  30. get
  31. {
  32. return mData;
  33. }
  34. }
  35.  
  36. #endregion Properties
  37. }
  38. }

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

UdpSocketHoster.cs

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Net;
  6. using System.Net.Sockets;
  7. using System.Runtime.Serialization.Formatters.Binary;
  8. using System.Text;
  9. using System.Threading;
  10. using System.Threading.Tasks;
  11. using System.Windows;
  12.  
  13. namespace ApplicationName
  14. {
  15. public class UdpSocketHoster
  16. {
  17. #region Fields (3)
  18.  
  19. private Thread mListenThread;
  20. private int mReceiverBuffer = 65536;
  21. private Socket mSocket;
  22.  
  23. #endregion Fields
  24.  
  25. #region Properties (3)
  26.  
  27. public string Ip
  28. {
  29. get;
  30. set;
  31. }
  32.  
  33. public int Port
  34. {
  35. get;
  36. set;
  37. }
  38.  
  39. public int ReceiverBuffer
  40. {
  41. get { return mReceiverBuffer; }
  42. set { mReceiverBuffer = value; }
  43. }
  44.  
  45. #endregion Properties
  46.  
  47. #region Delegates and Events (3)
  48.  
  49. // Events (3)
  50.  
  51. public event EventHandler ReceivedData;
  52. public event EventHandler StartListening;
  53. public event EventHandler StopListening;
  54. #endregion Delegates and Events
  55. #region Methods (4)
  56. // Public Methods (3)
  57. public void Start()
  58. {
  59. if (StartListening != null)
  60. {
  61. StartListening(this, new EventArgs());
  62. }
  63. mListenThread = new Thread(new ParameterizedThreadStart(startListen));
  64. mListenThread.Start();
  65. }
  66. public void Start(string ip, int port)
  67. {
  68. this.Ip = ip;
  69. this.Port = port;
  70. Start();
  71. }
  72. public void Stop()
  73. {
  74. if (StopListening != null)
  75. {
  76. StopListening(this, new EventArgs());
  77. }
  78. mSocket.Close();
  79. mListenThread.Abort();
  80. }
  81. // Private Methods (1)
  82. private void startListen(object sender)
  83. {
  84. //Setting Endpoint
  85. IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, Port);
  86. mSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
  87. //Binding Endpoint
  88. mSocket.Bind(endpoint);
  89. //Getting Client Ip
  90. IPEndPoint clientEndpoint = new IPEndPoint(IPAddress.Any, 0);
  91. EndPoint Remote = (EndPoint)(clientEndpoint);
  92. //Start loop for receiving data
  93. while (true)
  94. {
  95. try
  96. {
  97. int recv;
  98. byte[] receivePackage = new byte[mReceiverBuffer];
  99. //Receive data from client
  100. recv = mSocket.ReceiveFrom(receivePackage, ref Remote);
  101. //remove empty byte
  102. byte[] cropped = new byte[recv];
  103. Array.Copy(receivePackage, 0, cropped, 0, recv);
  104. String str = System.Text.Encoding.UTF8.GetString(cropped, 0, cropped.Length);
  105. ////Deserialize data
  106. //BinaryFormatter bf = new BinaryFormatter();
  107. //MemoryStream stream = new MemoryStream(receivePackage);
  108. //object data = bf.Deserialize(stream);
  109. if (ReceivedData != null)
  110. {
  111. ReceivedData(this, new ReceiveDataEventArgs(str));
  112. }
  113. }
  114. catch (Exception ex)
  115. {
  116. throw;
  117. }
  118. }
  119. }
  120. #endregion Methods
  121. }
  122. }

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

MainWindow.cs
  1. public partial class MainWindow : Window
  2. {
  3. UdpSocketHoster myhoster = new UdpSocketHoster();
  4.  
  5. public MainWindow()
  6. {
  7. InitializeComponent();
  8. // initial socket hoster
  9. initSocket();
  10.  
  11. }
  12. public void initSocket()
  13. {
  14. myhoster = new UdpSocketHoster();
  15. myhoster.ReceivedData += (o, e) => ReceiveData8000(e.Data.ToString());
  16. myhoster.StartListening += (o, e) => Console.WriteLine("Start Hosting...");
  17. myhoster.StopListening += (o, e) => Console.WriteLine("Stop Hosting...");
  18. myhoster.Start("127.0.0.1", 8000);
  19. }
  20.  
  21. // receive _data string
  22. public void ReceiveData8000(String _data)
  23. {
  24. Dispatcher.BeginInvoke(new Action(() =>
  25. {
  26. label_socket.Content = _data;
  27. ColorChange(_data);
  28.  
  29. }));
  30. }
  31.  
  32. // stop host when exit
  33. private void Window_main_Closed(object sender, EventArgs e)
  34. {
  35. myhoster.Stop();
  36. }
  37. }


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
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Net;
  6. using System.Net.Sockets;
  7. using System.Runtime.Serialization.Formatters.Binary;
  8. using System.Text;
  9. using System.Threading.Tasks;
  10.  
  11. namespace ApplicationName
  12. {
  13. public class UdpSocketSender
  14. {
  15. #region Fields (1)
  16.  
  17. private int mPackageBuffer = 1024;
  18.  
  19. #endregion Fields
  20.  
  21. #region Constructors (1)
  22.  
  23. public UdpSocketSender(string ip, int port)
  24. {
  25. this.Ip = ip;
  26. this.Port = port;
  27. }
  28.  
  29. #endregion Constructors
  30.  
  31. #region Properties (3)
  32.  
  33. public string Ip { get; set; }
  34.  
  35. public int PackageBuffer
  36. {
  37. get { return mPackageBuffer; }
  38. set { mPackageBuffer = value; }
  39. }
  40.  
  41. public int Port { get; set; }
  42.  
  43. #endregion Properties
  44.  
  45. #region Methods (1)
  46.  
  47. // Public Methods (1)
  48.  
  49. public void Send(string data)
  50. {
  51. //Setting Server Endpoint
  52. IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(Ip), Port);
  53. Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
  54. server.EnableBroadcast = true;
  55.  
  56. //Serialize Data
  57. byte[] package = new byte[mPackageBuffer];
  58. BinaryFormatter bf = new BinaryFormatter();
  59. MemoryStream stream = new MemoryStream();
  60. bf.Serialize(stream, data);
  61. package = stream.ToArray();
  62.  
  63. //Send Data
  64.  
  65. byte[] b = System.Text.Encoding.UTF8.GetBytes(data);
  66.  
  67. server.SendTo(b, b.Length, SocketFlags.None, endPoint);
  68. }
  69.  
  70. #endregion Methods
  71. }
  72. }

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

最後放上完整的MainWindow程式碼(包括receive跟send功能)
  1. public partial class MainWindow : Window
  2. {
  3. UdpSocketHoster myhoster = new UdpSocketHoster();
  4. UdpSocketSender mysender = new UdpSocketSender("127.0.0.1", 8000);
  5.  
  6. public MainWindow()
  7. {
  8. InitializeComponent();
  9. // initial socket hoster
  10. initSocket();
  11. // send socket
  12. mysender.Send("Test");
  13. }
  14. public void initSocket()
  15. {
  16. myhoster = new UdpSocketHoster();
  17. myhoster.ReceivedData += (o, e) => ReceiveData8000(e.Data.ToString());
  18. myhoster.StartListening += (o, e) => Console.WriteLine("Start Hosting...");
  19. myhoster.StopListening += (o, e) => Console.WriteLine("Stop Hosting...");
  20. myhoster.Start("127.0.0.1", 8000);
  21. }
  22.  
  23. // receive _data string
  24. public void ReceiveData8000(String _data)
  25. {
  26. Dispatcher.BeginInvoke(new Action(() =>
  27. {
  28. label_socket.Content = _data;
  29. ColorChange(_data);
  30.  
  31. }));
  32. }
  33.  
  34. // stop host when exit
  35. private void Window_main_Closed(object sender, EventArgs e)
  36. {
  37. myhoster.Stop();
  38. }
  39. }


沒有留言:

張貼留言