http://www.sufeinet.com/plugin.php?id=keke_group

苏飞论坛

 找回密码
 马上注册

QQ登录

只需一步,快速开始

分布式系统框架(V2.0) 轻松承载百亿数据,千万流量!讨论专区 - 源码下载 - 官方教程

HttpHelper爬虫框架(V2.7-含.netcore) HttpHelper官方出品,爬虫框架讨论区 - 源码下载 - 在线测试和代码生成

HttpHelper爬虫类(V2.0) 开源的爬虫类,支持多种模式和属性 源码 - 代码生成器 - 讨论区 - 教程- 例子

查看: 57151|回复: 13

[UDP] C#UDP入门|Socket通信|UdpClient通信

[复制链接]
发表于 2012-7-11 10:26:42 | 显示全部楼层 |阅读模式
  UDP 是User Datagram Protocol的简称, 中文名是用户数据包协议,是 OSI 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。它是IETF RFC 768是UDP的正式规范。      UDP报头

  UDP报头由4个域组成,其中每个域各占用2个字节,具体如下:

  源端口号

  目标端口号

  数据报长度

  校验值

  UDP协议使用端口号为不同的应用保留其各自的数据传输通道。UDP和TCP协议正是采用这一机制实现对同一时刻内多项应用同时发送和接收数据的支持。数据发送一方(可以是客户端或服务器端)将UDP数据报通过源端口发送出去,而数据接收一方则通过目标端口接收数据。有的网络应用只能使用预先为其预留或注册的静态端口;而另外一些网络应用则可以使用未被注册的动态端口。因为UDP报头使用两个字节存放端口号,所以端口号的有效范围是从0到65535。一般来说,大于49151的端口号都代表动态端口。

  数据报的长度是指包括报头和数据部分在内的总字节数。因为报头的长度是固定的,所以该域主要被用来计算可变长度的数据部分(又称为数据负载)。数据报的最大长度根据操作环境的不同而各异。从理论上说,包含报头在内的数据报的最大长度为65535字节。不过,一些实际应用往往会限制数据报的大小,有时会降低到8192字节。

  UDP协议使用报头中的校验值来保证数据的安全。校验值首先在数据发送方通过特殊的算法计算得出,在传递到接收方之后,还需要再重新计算。如果某个数据报在传输过程中被第三方篡改或者由于线路噪音等原因受到损坏,发送和接收方的校验计算值将不会相符,由此UDP协议可以检测是否出错。这与TCP协议是不同的,后者要求必须具有校验值。


  许多链路层协议都提供错误检查,包括流行的以太网协议,也许想知道为什么UDP也要提供检查和。其原因是链路层以下的协议在源端和终端之间的某些通道可能不提供错误检测。虽然UDP提供有错误检测,但检测到错误时,UDP不做错误校正,只是简单地把损坏的消息段扔掉,或者给应用程序提供警告信息。

UDP协议的几个特性


  (1) UDP是一个无连接协议,传输数据之前源端和终端不建立连接,当它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上。在发送端,UDP传送数据的速度仅仅是受应用程序生成数据的速度、计算机的能力和传输带宽的限制;在接收端,UDP把每个消息段放在队列中,应用程序每次从队列中读一个消息段。

  (2) 由于传输数据不建立连接,因此也就不需要维护连接状态,包括收发状态等,因此一台服务机可同时向多个客户机传输相同的消息。

  (3) UDP信息包的标题很短,只有8个字节,相对于TCP的20个字节信息包的额外开销很小。

  (4) 吞吐量不受拥挤控制算法的调节,只受应用软件生成数据的速率、传输带宽、源端和终端主机性能的限制。

  (5)UDP使用尽最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的链接状态表(这里面有许多参数)。

  (6)UDP是面向报文的。发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付给IP层。既不拆分,也不合并,而是保留这些报文的边界,因此,应用程序需要选择合适的报文大小。 

  虽然UDP是一个不可靠的协议,但它是分发信息的一个理想协议。例如,在屏幕上报告股票市场、在屏幕上显示航空信息等等。UDP也用在路由信息协议RIP(Routing Information Protocol)中修改路由表。在这些应用场合下,如果有一个消息丢失,在几秒之后另一个新的消息就会替换它。UDP广泛用在多媒体应用中,例如,Progressive Networks公司开发的RealAudio软件,它是在因特网上把预先录制的或者现场音乐实时传送给客户机的一种软件,该软件使用的RealAudio audio-on-demand protocol协议就是运行在UDP之上的协议,大多数因特网电话软件产品也都运行在UDP之上。

1.我们先使用Socket的方法来实现

服务器代码:
[C#] 纯文本查看 复制代码
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 );
            }
        }

    }
}

客户端代码 :
[C#] 纯文本查看 复制代码
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 ();            
        }

    }
}


2.下面咱们再来使用UdpClient 来实现他们之间的通信服务器端代码
[C#] 纯文本查看 复制代码
using   System;   
  using   System.Net;   
  using   System.Net.Sockets;   
  using   System.Text;   
    
  public   class   Custom   {   
    
        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   {   
              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;   
      }   
  }   


客户端代码:
[C#] 纯文本查看 复制代码
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;   
      }   
  }

如果您是采用窗体的形式建议使用这种格式,否则在接收数据时可能会出现死机的现象

[C#] 纯文本查看 复制代码
// 创建一个子线程
            Thread thread = new Thread(
                delegate()
                {
                    try
                    {
                        //在这里写你的代码
                    }
                    catch (Exception )
                    {

                    }
                }
            );
            thread.Start();


本帖被以下淘专辑推荐:



1. 开通SVIP会员,免费下载本站所有源码,不限次数据,不限时间
2. 加官方QQ群,加官方微信群获取更多资源和帮助
3. 找站长苏飞做网站、商城、CRM、小程序、App、爬虫相关、项目外包等点这里
发表于 2012-10-12 15:13:41 | 显示全部楼层
怎么下载啊!!!1
发表于 2012-11-13 11:56:18 | 显示全部楼层
地久天长-孔德姣 发表于 2012-10-12 15:13
怎么下载啊!!!1

这个是直接贴的代码,你直接使用代码就行了,打包的没有
发表于 2013-5-22 22:33:09 | 显示全部楼层
受教了,学习中……
发表于 2013-12-19 13:15:34 | 显示全部楼层
谢谢分享。
回复

使用道具 举报

发表于 2013-12-19 13:22:47 | 显示全部楼层
现在没时间看,先留个记号,回头细细品味!
发表于 2014-4-29 14:10:52 | 显示全部楼层
楼主,代码不知道应该怎样放才能运行起来?我这样放貌似不行。。。求指教。。。
QQ图片20140429141015.jpg
发表于 2014-4-29 14:18:05 | 显示全部楼层
我看错了 不好意思 楼主发的应该是两种方式 我看成一种了~
发表于 2014-5-29 21:51:13 | 显示全部楼层
我只是路过看看的。
发表于 2014-8-19 11:05:29 | 显示全部楼层
学习一下,谢谢楼主
您需要登录后才可以回帖 登录 | 马上注册

本版积分规则

QQ|手机版|小黑屋|手机版|联系我们|关于我们|广告合作|苏飞论坛 ( 豫ICP备18043678号-2)

GMT+8, 2024-12-23 00:21

© 2014-2021

快速回复 返回顶部 返回列表