C# 实现UPD 协议

news/2025/2/8 16:56:45 标签: c#, 操作系统, python

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

    本文由ligong528贡献
    doc文档可能在WAP端浏览体验不佳。建议您优先选择TXT,或下载源文件到本机查看。
    C#实现 UDP 协议 实现 一. 走进 UDP 协议: UDP(UserDatagramProtocol)协议就是"用户数据报协议",它是一种无连接的协议, 无连接主要是和 TCP 协议相比较的。我们知道当利用 TCP 协议传送数据的时候,首先必须先建 立连接(也就是所谓的握手)才可以传输数据。而当计算机利用 UDP 协议进行数据传输的时候, 发送方只需要知道对方的 IP 地址和端口号就可以发送数据,而并不需要进行连接。当然如果你 非要进行连接,通过 VisualC#也是可以实现的,但前提是要确定连接的远程主机的端口号处于 监听状态,否则程序会出现不必要的错误,但这是种画蛇添足的做法,不仅丢失了 UDP 协议的 无连接传送数据的特点和优点, 而且还给程序运行带来了不安定的因素。 所以这种方法并不值得 提倡。 由于 UDP 协议并不需要进行确定的连接,所以编写基于 UDP 协议的应用程序比起编写基 于 TCP 协议的应用程序要简单些(程序中可以不需要考虑连接和一些异常的捕获工作)。但同 时也给基于 UDP 协议编写的程序带来了一个致命的缺点, UDP 由于不提供可靠数据的传输, 当 计算机之间利用 UDP 协议传送数据的时候,发送方只管发送数据,而并不确认数据是否被对方 接收。这样就会导致某些 UDP 协议数据包在传送的过程中丢失,尤其网络质量不令人满意的情 况下,丢失数据包的现象会更严重。这就是为什么在网络上传输重要数据不采用 UDP 协议的原 因。 但是我们也不能因为这一个缺点就全面否定 UDP 协议,这是因为虽然利用 UDP 协议来传 送安全性要求高的数据是不适合的, 但对于那些不重要的数据, 或者即使丢失若干数据包也不影 响整体性的数据,如音频数据,视频数据等,采用 UDP 协议就是一个非常不错的选择。如目前 网络流行的很多即时聊天程序,如 OICQ 和 ICQ 等,采用的就是 UDP 协议。同时虽然 UDP 协 议无法保证数据可靠性,但具有对网络资源开销较小,数据处理速度快的优点,所以在有些对数 据安全性要求不是很高的情况下,采用 UDP 协议也是一个非常不错的选择。 总结一下上面的内容,可见 UDP 是一种不面向连接的网络协议,既有其优点,也有其不足, 具体如下: 1.基于 UDP 协议的网络应用程序,实现起来比较简单,并且基于 UDP 协议的网络应用程序在 运行时,由于受到环境影响较小,所以不容易出错。 2.UDP 协议占用网络资源较少,数据处理较快,所以在网络中传送对安全性要求不是十分高数 据时,其优点比较明显。所谓对安全性要求不高的数据,是指那些不重要的数据,或者是即使丢 失若干数据,也不影响其整体的数据,如音频数据等。目前很多流行的网络应用程序都是基于 UDP 协议的,如 OICQ、ICQ 等。 3.由于其不是面向连接的网络协议,其缺点也是非常明显的,有些时候甚至是致命的。因为使用 UDP 协议来传送数据,在数据发送后,在发送方并不确认对方是否接收到。这样就可能导致传 送的数据在网络中丢失,尤其在网络条件并不很好的情况下,丢失数据包的现象就更多。所以传 送重要数据一般不采用 UDP 协议。 二.简介 VisualC#发送、接收 UDP 数据包使用的主要类及其用法: 用 VisualC#实现 UDP 协议,最为常用,也是最为关键的类就是 UdpClient,UdpClient 位于命名空间 System.Net.Sockets 中, VisualC#发送、 接收 UDP 数据包都是通过 UdpClient 类的。表 01 和表 02 是 UdpClient 类中常用方法和属性及其简要说明。 方法 Close Connect 说明 关闭 UDP 连接 建立与远程主机的连接
    DropMulticastGroup 退出多路广播组 JoinMulticastGroup 将 UdpClient 添加到多路广播组 Receive Send 返回已由远程主机发送的 UDP 数据文报 将 UDP 数据文报发送到远程主机
    表 01:UdpClient 类中常用方法及其说明。
    属性
    说明
    Active 获取或设置一个值,该值指示是否已建立了与远程主机的连接 Client 获取或设置基础网络套接字 表 02:UdpClient 类中常用方法及其说明。 1.Visual C#使用 UdpClient 类发送 UDP 数据包: 在具体使用中,一般分成二种情况: (1). 知道远程计算机 IP 地址: "Send"方法的调用语法如下:
    public int Send ( byte[] dgram , int bytes , IPEndPoint endPoint ) ;
    参数说明: dgram 要发送的 UDP 数据文报(以字节数组表示)。 bytes 数据文报中的字节数。 endPoint 一个 IPEndPoint,它表示要将数据文报发送到的主机和端口。 返回值 已发送的字节数。 下面使用 UdpClient 发送 UDP 数据包的具体的调用例子:
    IPAddress HostIP = new IPAddress.Parse ( "远程计 算机 IP 地址" ) ; IPEndPoint host = new IPEndPoint ( HostIP , 8080 ) ; UdpClient.Send ( "发送的字节" , "发送 的字节长度" , host ) ;
    (2). 知道远程计算机名称:: 知道远程计算机名称后,利用"Send"方法直接把 UDP 数据包发送到远程主机的指定端口号上 了,这种调用方式也是最容易的,语法如下:
    public int Send ( byte[ ] dgram , int bytes ,
    string hostname , int port ) ;
    参数说明: dgram 要发送的 UDP 数据文报(以字节数组表示)。 bytes 数据文报中的字节数。 hostname 要连接到的远程主机的名称。 port 要与其通讯的远程端口号。 返回值 已发送的字节数。 2.Visual C#使用 UdpClient 类接收 UDP 数据包: 接收 UDP 数据包使用的是 UdpClient 中的"Receive"方法。此方法的调用语法如下:
    public byte [] Receive ( ref IPEndPoint remoteEP ) ;
    参数 remoteEP 是一个 IPEndPoint 类的实例,它表示网络中发送此数据包的节点。 如果指定了远程计算机要发送到本地机的端口号, 也可以通过侦听本地端口号来实现对数据的获 取,下面就是通过侦听本地端口号"8080"来获取信息代码:
    server = new UdpClient ( ) ; receivePoint = new IPEndPoint (new IPAddress ( "127.0.0.1" ) , 8080 ) ; byte[] recData = server.Receive ( ref receivePoint ) ;
    协议之网络对时系统的体系结构及功能简介: 三.Visual C#实现 UDP 协议之网络对时系统的体系结构及功能简介: # 在局域网中有很多应用软件为了协同工作,需要保证客户机上时间统一,而为了实现这一点,通 常的做法是客户机从一个时间相对正确的服务器读取时间, 以此来校正本地时间。 如经常看到的 GPS 对时系统等。本节编写的局域网上对时系统的主要的功能是保证局域网上计算机时间、日 期的统一。网络对时程序是体系结构分成服务器端程序和客户端程序二个部分,具体的作法是: 在同一个网段上, 固定一台计算机作为对时的服务器, 在这个网段的所有计算机都可以读取这台 服务器上的时间和日期,并依此服务器上的时间和日期为基准,来确定本地的时间和日期。在服 务器端程序需要达到以下功能: 能够接收局域网中任一台客户机的请求 记录请求客户机的计算机名称,和请求时间 准确发送服务器端的时间和日期 端程序要达到以下功能: 能够设定服务器的主机或者 IP 地址 能够接收服务器端发送的时间、日期信息 能够以接收的服务器端时间、日期为基准,校正本地时间 因此在具体用 Visual C#实现网络对时系统时就包括二个部分:服务器端程序和客户端程序。
    下面首先介绍 Visual C#实现网络对时系统中服务器端程序的具体步骤。 四.Visual C#实现网络对时系统之服务器端程序的具体步骤: #实现网络对时系统之服务器端程序的具体步骤: 服务器端程序比客户端程序相对要简单,主要因是服务器端程序的工作比较简单,就 是接收客户端的对时请求、发送服务器端的时间数据。而于客户端不仅要传送和接收数据,还要 把服务器端的时间提取出来,并以此来修改本地计算机的时间、日期。下面是用 Visual C#实 现网络对时系统之服务器端程序的具体步骤步骤。 1.启动 Visual Studio .Net。 2.选择菜单【文件】|【新建】|【项目】后,弹出【新建项目】对话框。 3.将【项目类型】设置为【Visual C#项目】。 4.将【模板】设置为【Windows 应用程序】。 5.在【名称】文本框中输入【UDP 对时服务器端】。 6.在【位置】的文本框中输入【E:\VS.NET 项目】,然后单击【确定】按钮 7.在【解决方案资源管理器】窗口中,双击 Form1.cs 文件,进入 Form1.cs 文件的编辑界面。 8.在 Form1.cs 文件的开头,用下列导入命名空间代码替代系统缺省的导入命名空间代码。
    using System ; using System.Drawing ; using System.Collections ; using System.ComponentModel ; using System.Windows.Forms ; using System.Data ; using System.Net ; using System.Net.Sockets ; using System.Threading ; //程序中使用到线程 using System.Text ; //程序中使用到编码
    9.切换到【Form1.cs(设计)】窗口,并从【工具箱】中的【Windows 窗体组件】中往窗体 中拖入下列组件,并执行相应操作: 一个 Label 组件,显示对时服务器正在运行信息 一个 ListBox 组件,名称为 listBox1,用以显示客户端和服务器端交流的日志 一个 Button 组件,名称为 button1,并在其拖入窗体后,双击,则系统会在 Form1.cs 文件 中产生其 Click 事件对应的处理代码。 10.在 【解决方案资源管理器】 窗口中, 双击 Form1.cs 文件, 进入 Form1.cs 文件的编辑界面。 在 Form1.cs 中的 class 代码区添加下列代码,下列代码是定义程序中使用的全局变量和创建 全局使用的实例:
    private UdpClient server ; private IPEndPoint receivePoint ; private int port = 8080 ; //定义端口号 private int ip = 127001 ; //设定本地 IP 地址
    private Thread startServer ;
    11.以下面代码替代系统产生的 InitializeComponent 过程。
    private void InitializeComponent ( ) { this.listBox1 = new System.Windows.Forms.ListBox ( ) ; this.label1 = new System.Windows.Forms.Label ( ) ; this.button1 = new System.Windows.Forms.Button ( ) ; this.SuspendLayout ( ) ; this.listBox1.ItemHeight = 12 ; this.listBox1.Location = new System.Drawing.Point ( 14 , 40 ) ; this.listBox1.Name = "listBox1" ; this.listBox1.Size = new System.Drawing.Size ( 268 , 220 ) ; this.listBox1.TabIndex = 0 ; this.label1.ForeColor = System.Drawing.Color.Red ; this.label1.Location = new System.Drawing.Point ( 44 , 10 ) ; this.label1.Name = "label1" ; this.label1.Size = new System.Drawing.Size ( 210 , 24 ) ; this.label1.TabIndex = 1 ; this.label1.Text = "UDP 对时服务器端正 在运行......" ; this.button1.FlatStyle = System.Windows.Forms.FlatStyle.Flat ; this.button1.Location = new System.Drawing.Point ( 106 , 278 ) ; his.button1.Name = "button1" ; this.button1.Size = new System.Drawing.Size ( 75 , 34 ) ; this.button1.TabIndex = 2 ; this.button1.Text = "清除信息" ; this.button1.Click += new System.EventHandler ( this.button1_Click ) ; this.AutoScaleBaseSize = new System.Drawing.Size ( 6 , 14 ) ;
    this.ClientSize = new System.Drawing.Size ( 300 , 329 ) ; this.Controls.AddRange ( new System.Windows.Forms.Control[] { this.button1 , this.listBox1 , this.label1} ) ; this.MaximizeBox = false ; this.Name = "Form1" ; this.Text = "UDP 对时服务器端" ; this.Load += new System.EventHandler ( this.Form1_Load ) ; this.ResumeLayout ( false ) ; }
    至此,【UDP 对时服务器端】项目的界面设计和功能实现的前期工作就完成了,设计界面如图 01 所示:
    :【UDP 对时服务器端】项目的设计界面 对时服务器端】 图 01:【 :【 12.在 Form1.cs 文件中的 InitializeComponent 过程的后面添加下面代码,下列代码是定义 过程"start_server"。此过程的功能是获取客户端对时请求数据,并向客户端发送服务器当前 时间和日期。
    public void start_server ( ) { while ( true ) {
    //接收从远程主机发送到本地 8080 端口的 数据 byte[] recData = server.Receive ( ref receivePoint ) ; ASCIIEncoding encode = new ASCIIEncoding ( ) ; //获得客户端请求数据 string Read_str = encode.GetString ( recData ) ; //提取客户端的信息,存放到定义为 temp 的字符串数组中 string[] temp = Read_str.Split ( "/".ToCharArray ( ) ) ; //显示端口号的请求信息 listBox1.Items.Add ( "时间:"+ DateTime.Now. ToLongTimeString ( ) + " 接收信息如 下:" ) ; listBox1.Items.Add ( "客户机:" + temp[0] ) ; listBox1.Items.Add ( "端口号:" + temp[1] ) ; //发送服务器端时间和日期 byte[] sendData =encode.GetBytes ( System.DateTime.Now.ToString ( ) ) ; listBox1.Items.Add ( "发送服务器时间! " ) ; //对远程主机的指定端口号发送服务器时 间 server.Send ( sendData , sendData.Length , temp[0] , Int32.Parse ( temp[1] ) ) ; } }
    请注意:上述代码中约定客户机程序发送对时请求信息到服务器的8080 端口号。服务器端程 序接收发送到本地 8080 端口号的数据就完成了数据接收。为了能够让服务器端程序知道是那 台客户机提出请求和要把对时信息发送到客户机的那个端口号上, 客户端程序对发送的对时请求 信息进行了设计。客户端的对时请求信息结构为: 计算机名称 + / + 客户机接收信息端口号 这样如果客户端计算机名称为:majinhu,接收服务器端时间数据的端口号是 8080,则客户端 程序发送的对时请求数据就为:majinhu/8080。 服务器端程序在接收到客户端对时请求数据, 并进行分析后, 就能够通过 UdpClient 类的 Send 方法准确的把服务器端当前的时间和日期发送到客户端指定的端口号上。 这样客户端程序通过读 取指定的端口号, 就能够获得服务器端当前的时间和日期, 从而以此来修正客户端的时间和日期
    了。 13.在"start_server"过程之后面添加下面代码,下列代码是定义"run"过程。"run"过程的作用 是创建一个线程实例,并以"start_server"过程来初始化线程实例。之所以采用线程是因为服 务器端程序需要不间断读取发送到 8080 端口号,并且 Receive 方法是一个阻塞式方法。采用 线程就是为了保证服务器端程序正常运行:
    public void run ( ) { //利用本地 8080 端口号来初始化一个 UDP 网络服务 server = new UdpClient ( port ) ; receivePoint = new IPEndPoint ( new IPAddress ( ip ) , port ) ; //开一个线程 startServer = new Thread ( new ThreadStart ( start_server ) ) ; //启动线程 startServer.Start ( ) ; }
    14.在 Form1.cs 中的 Main 函数之后添加下列代码,下列代码是定义"Form1_Load"事件,在 此事件中将调用"run"过程,这样当服务器端程序运行后,就启动网络对时服务:
    private void Form1_Load ( object sender , System.EventArgs e ) { //启动对时服务 run ( ) ; }
    15.在 Form1.cs 文件中的"Form1_Load"事件之后, 添加下列代码, 下列代码是定义 button1 的"Click"事件,此事件的作用是清除服务器端程序显示的日志信息:
    private void button1_Click ( object sender , System.EventArgs e ) { //清除服务器端程序日志 listBox1.Items.Clear ( ) ; }
    16.用下列代码替换 Form1.cs 中的 Dispose 方法。下列代码的功能是手动收集程序中使用的 资源:
    protected override void Dispose ( disposing ) {
    bool
    try { //关闭线程 startServer.Abort ( ) ; //清除资源 server.Close ( ) ; } catch { } ; if ( disposing ) { if ( components != null ) { components.Dispose ( ) ; } } base.Dispose ( disposing ) ; }
    至此,在上述步骤都正确完成,【UDP 对时服务器端】项目的全部工作就完成了。图 02【UDP 对时服务器端】运行后的界面,在日志信息中记录了对时请求客户机的名称,发送对时数据的端 口号以及客户端请求的时间:
    :【UDP 对时服务器端】项目的运行界面 对时服务器 服务器端 项目的运行界面 图 02:【 :【 c# 得到局域网中可用 SqlServer 服务器列表(转) 服务器列表 转
    static void Main(string[] args) { // Retrieve the enumerator instance and then the data. SqlDataSourceEnumerator instance =SqlDataSourceEnumerator.Instance; System.Data.DataTable table = instance.GetDataSources(); // Display the contents of the table. DisplayData(table); Console.WriteLine("Press any key to continue."); Console.ReadKey(); } private static void DisplayData(System.Data.DataTable table) { foreach (System.Data.DataRow row in table.Rows) { foreach (System.Data.DataColumn col in table.Columns) { Console.WriteLine("{0} = {1}", col.ColumnName, row[col]); } Console.WriteLine("==="); } }
 

转载于:https://my.oschina.net/u/615762/blog/1524551


http://www.niftyadmin.cn/n/1376592.html

相关文章

Python变量类型

变量类型 关键字严格意义上来讲python只有一个类型标准数据类型6种 数字 整数浮点数科学计数法复数 字符串 三引号可以表示多行,单双引号默认一行 None类型 None表示没有,通常用来占位 运算符 加减乘跟数学一致普通除(/)整除&…

surface pro app

fresh paintpotplayer acg播放器 http://potplayer.daum.net/?langzh_CNnebooneNoteGesture Signxodo pdf reader and editor

阮一峰 ES6

阮一峰 ES6:http://es6.ruanyifeng.com/#docs/module转载于:https://www.cnblogs.com/bydzhangxiaowei/p/9947078.html

线性回归模型

一元线性回归模型的介绍与应用 一元线性回归模型 回归方程形式:,i1,2,...n,其中需满足以下四个假设条件 a.正态性假设,即是服从正态分布的随机变量 b.无偏性假设,即E()0 c.同方差性假设,即所有的方差都相同&#…

java工具类Collections

Collections的常用方法1. sort(list,comparator)sort(list)在使用时,集合中的对象要可序列化,即实现comparable方法或者传入一个已知类型的比较器对象,默认调用的是compareTo()方法2. shuffle(list) 将元素进行随机排列,使顺…

vue引用百度地图,drawingManager.setDrawingMode不能接受参数,否则会报错

直接上部分代码: 引用百度地图后,没报错,但是鼠标绘制线路时报错: // 绘制点线 this.drawingManager new window.BMapLib.DrawingManager(this.map, { isOpen: true, //是否开启绘制模式 //enableDrawingTool: true, //是否显示…

11. Container With Most Water

给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多…

核心基础(二)--进制转化以及字符串和格式化

如何表示二进制、八进制和十六进制 二进制:数值前面加0b八进制:数值前面加0o十六进制:数值前面加0x二进制转换函数:bin-->二进制转换函数;int-->十进制转换函数;hex-->十六进制转换函数&#xff…