程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 基於C#的UDP協議的同步通訊完成代碼

基於C#的UDP協議的同步通訊完成代碼

編輯:C#入門知識

基於C#的UDP協議的同步通訊完成代碼。本站提示廣大學習愛好者:(基於C#的UDP協議的同步通訊完成代碼)文章只能為提供參考,不一定能成為您想要的結果。以下是基於C#的UDP協議的同步通訊完成代碼正文


一、摘要

總結基於C#的UDP協議的同步通訊。

 二、實驗平台

Visual Studio 2010

 三、實驗原理

UDP傳輸協議同TCP傳輸協議的區別可查閱相關文檔,此處不再贅述。 

四、實例

4.1 采用socket完成UDP

由於UDP是一種無銜接的協議。因而,為了使服務器使用可以發送和接納UDP數據包,則需求做兩件事情:

(1) 創立一個Socket對象;

(2) 將創立的套接字對象與本地IPEndPoint停止綁定。

完成上述步驟後,那麼創立的套接字就可以在IPEndPoint上接納流入的UDP數據包,或許將流出的UDP數據包發送到網絡中其他恣意設備。運用UDP停止通訊時,不需求銜接。由於異地的主機之間沒有樹立銜接,所以UDP不能運用規范的Send()和Receive()t套接字辦法,而是運用兩個其他的辦法:SendTo()和ReceiveFrom()。

SendTo()辦法指定要發送的數據,和目的機器的IPEndPoint。該辦法有多種不同的運用辦法,可以依據詳細的使用停止選擇,但是至多要指定數據包和目的機器。如下:

SendTo(byte[] data,EndPoint Remote)

ReceiveFrom()辦法同SendTo()辦法相似,但是運用EndPoint對象聲明的方式不一樣。應用ref修飾,傳遞的不是一個EndPoint對象,而是將參數傳遞給一個EndPoint對象。

UDP使用不是嚴厲意義上的真正的服務器和客戶機,而是對等的關系,即沒有主與次的關系。為了簡便起見,依然把上面的這個使用叫做UDP服務器。

服務器端代碼:

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;

namespace UDP
{
 class Program
 {
  static void Main(string[] args)
  {
   int recv;
   byte[] data = new byte[1024];

   //失掉本機IP,設置TCP端口號   
   IPEndPoint ip = new IPEndPoint(IPAddress.Any, 8001);
   Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

   //綁定網絡地址
   newsock.Bind(ip);

   Console.WriteLine("This is a Server, host name is {0}", Dns.GetHostName());

   //等候客戶機銜接
   Console.WriteLine("Waiting for a client");

   //失掉客戶機IP
   IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
   EndPoint Remote = (EndPoint)(sender);
   recv = newsock.ReceiveFrom(data, ref Remote);
   Console.WriteLine("Message received from {0}: ", Remote.ToString());
   Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));

   //客戶機銜接成功後,發送信息
   string welcome = "你好 ! ";

   //字符串與字節數組互相轉換
   data = Encoding.ASCII.GetBytes(welcome);

   //發送信息
   newsock.SendTo(data, data.Length, SocketFlags.None, Remote);
   while (true)
   {
    data = new byte[1024];
    //發送接納信息
    recv = newsock.ReceiveFrom(data, ref Remote);
    Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));
    newsock.SendTo(data, recv, SocketFlags.None, Remote);
   }
  }

 }
}

關於接納流入的UDP服務器順序來說,必需將順序與本地零碎中指定的UDP端口停止綁定。這就可以經過運用適宜的本地IP地址創立一個IPEndPoint對象,以及適宜的UDP端口號。上述范例順序中的UDP服務器可以在端口8001從網絡上接納恣意流入的UDP數據包。

UDP客戶機順序與服務器順序十分相似。

由於客戶機不需求在指定的UDP端口等候流入的數據,因而,不運用Bind()辦法,而是運用在數據發送時零碎隨機指定的一個UDP端口,而且運用同一個端口接納前往的音訊。在開發產品時,要為客戶機指定一套UDP端口,以便服務器和客戶機順序運用相反的端口號。UDP客戶機順序首先定義一個IPEndPoint,UDP服務器將發送數據包到這個IPEndPoint。假如在近程設備上運轉UDP服務器順序,在IPEndPoint定義中必需輸出適當的IP地址和UDP端口號信息。

客戶端代碼:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;

namespace UDPClient
{
 class Program
 {
  static void Main(string[] args)
  {
   byte[] data = new byte[1024];
   string input, stringData;

   //構建TCP 服務器
   Console.WriteLine("This is a Client, host name is {0}", Dns.GetHostName());

   //設置服務IP,設置TCP端口號
   IPEndPoint ip = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8001);

   //定義網絡類型,數據銜接類型和網絡協議UDP
   Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

   string welcome = "你好! ";
   data = Encoding.ASCII.GetBytes(welcome);
   server.SendTo(data, data.Length, SocketFlags.None, ip);
   IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
   EndPoint Remote = (EndPoint)sender;

   data = new byte[1024];
   //關於不存在的IP地址,參加此行代碼後,可以在指定時間內解除阻塞形式限制
   int recv = server.ReceiveFrom(data, ref Remote);
   Console.WriteLine("Message received from {0}: ", Remote.ToString());
   Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));
   while (true)
   {
    input = Console.ReadLine();
    if (input == "exit")
     break;
    server.SendTo(Encoding.ASCII.GetBytes(input), Remote);
    data = new byte[1024];
    recv = server.ReceiveFrom(data, ref Remote);
    stringData = Encoding.ASCII.GetString(data, 0, recv);
    Console.WriteLine(stringData);
   }
   Console.WriteLine("Stopping Client.");
   server.Close();
  }

 }
}

上述代碼的完成邏輯為:相關設置完成後,服務器端先向客戶端發送信息,之後客戶端經過鍵盤發送字符串,服務器端收到後再發送給客戶端,如此循環。

4.2 采用UDPClient類完成

服務器端代碼:

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

public class Custom
{
 // 設置IP,IPV6
 private static readonly IPAddress GroupAddress = IPAddress.Parse("IP地址");
 // 設置端口
 private const int GroupPort = 11000;

 private static void StartListener()
 {
  bool done = false;

  UdpClient listener = new UdpClient();

  IPEndPoint groupEP = new IPEndPoint(GroupAddress, GroupPort);

  try
  {
   //IPV6,組播
   listener.JoinMulticastGroup(GroupAddress);

   listener.Connect(groupEP);

   while (!done)
   {
    Console.WriteLine("Waiting for broadcast");

    byte[] bytes = listener.Receive(ref groupEP);

    Console.WriteLine("Received broadcast from {0} :\n {1}\n", groupEP.ToString(), Encoding.ASCII.GetString(bytes, 0, bytes.Length));
   }

   listener.Close();

  }
  catch (Exception e)
  {
   Console.WriteLine(e.ToString());
  }

 }

 public static int Main(String[] args)
 {
  StartListener();

  return 0;
 }
}

客戶端代碼:

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

public class Client
{

 private static IPAddress GroupAddress = IPAddress.Parse("IP地址");

 private static int GroupPort = 11000;

 private static void Send(String message)
 {
  UdpClient sender = new UdpClient();

  IPEndPoint groupEP = new IPEndPoint(GroupAddress, GroupPort);

  try
  {
   Console.WriteLine("Sending datagram : {0}", message);

   byte[] bytes = Encoding.ASCII.GetBytes(message);

   sender.Send(bytes, bytes.Length, groupEP);

   sender.Close();

  }
  catch (Exception e)
  {
   Console.WriteLine(e.ToString());
  }

 }

 public static int Main(String[] args)
 {
  Send(args[0]);

  return 0;
 }
}

以上代碼需求闡明的是:

(1) 上述代碼是基於IPV6地址的組播形式。IPv4中的播送(broadcast)可以招致網絡功能的下降甚至播送風暴(broadcast storm)。在IPv6中就不存在播送這一概念了,取而代之的是組播(multicast)和恣意播(anycast)。

(2) IPV6地址表示辦法:

a) X:X:X:X:X:X:X:X(每個X代表16位的16進制數字),不區分大小寫;

b) 排頭的0可省略,比方09C0就可以寫成9C0,0000可以寫成0;

c) 延續為0的字段可以以::來替代,但是整個地址中::只能呈現一次,比方FF01:0:0:0:0:0:0:1就可以簡寫成FF01::1。

(3) 假如是采用窗體的方式建議運用這種格式,否則在接納數據時能夠會呈現死機的景象。

// 創立一個子線程

   Thread thread = new Thread(
    delegate()
    {
     try
     {
      //在這裡寫你的代碼
     }
     catch (Exception )
     {

     }
    }
   );

   thread.Start();

以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支持。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved