• 技术文章 >后端开发 >C#.Net教程

    详解基于C#的UDP协议的同步通信的示例代码

    黄舟黄舟2017-03-23 11:38:10原创1009
    本篇文章主要介绍了基于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();

    以上就是详解基于C#的UDP协议的同步通信的示例代码的详细内容,更多请关注php中文网其它相关文章!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    上一篇:详细介绍C#基于纯数学方法递归实现货币数字转换中文功能的案例 下一篇:c#中文转拼音without CJK的代码分享
    PHP编程就业班

    相关文章推荐

    • 分享一道逻辑面试题,看看你能答对吗!• C++设计模式浅识装饰模式• SUNWEN教程之----C#进阶(五)• asp.net core mvc实现文件上传实例• SUNWEN教程之----C#进阶(十一)

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网