initializecomponent:用VisualC#实现UDP协议

 2021-07-15 8:10    77  

由于UDP协议并不需要进行确定的连接,所以编写基于UDP协议的应用程序比起编写基于TCP协议的应用程序要简单些(程序中可以不需要考虑连接和一些异常的捕获工作)initializecomponent。但同时也给基于UDP协议编写的程序带来了一个致命的缺点,UDP由于不提供可靠数据的传输,当计算机之间利用UDP协议传送数据的时候,发送方只管发送数据,而并不确认数据是否被对方接收。这样就会导致某些UDP协议数据包在传送的过程中丢失,尤其网络质量不令人满意的情况下,丢失数据包的现象会更严重。这就是为什么在网络上传输重要数据不采用UDP协议的原因。

initializecomponent:用VisualC#实现UDP协议

  但是我们也不能因为这一个缺点就全面否定UDP协议initializecomponent,这是因为虽然利用UDP协议来传送安全性要求高的数据是不适合的,但对于那些不重要的数据,或者即使丢失若干数据包也不影响整体性的数据,如音频数据,视频数据等,采用UDP协议就是一个非常不错的选择。如目前网络流行的很多即时聊天程序,如OICQ和ICQ等,采用的就是UDP协议。同时虽然UDP协议无法保证数据可靠性,但具有对网络资源开销较小,数据处理速度快的优点,所以在有些对数据安全性要求不是很高的情况下,采用UDP协议也是一个非常不错的选择。

initializecomponent:用VisualC#实现UDP协议

  总结一下上面的内容,可见UDP是一种不面向连接的网络协议,既有其优点,也有其不足,具体如下initializecomponent:

initializecomponent:用VisualC#实现UDP协议

1.基于UDP协议的网络应用程序,实现起来比较简单,并且基于UDP协议的网络应用程序在运行时,由于受到环境影响较小,所以不容易出错。

initializecomponent:用VisualC#实现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

关闭 UDP 连接

Connect

建立与远程主机的连接

DropMulticastGroup

退出多路广播组

JoinMulticastGroup

将 UdpClient 添加到多路广播组

Receive

返回已由远程主机发送的 UDP 数据文报

Send

将 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所示:

图01:【UDP对时服务器端】项目的设计界面 图01:【UDP对时服务器端】项目的设计界面

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 ( bool disposing ){ try { //关闭线程 startServer.Abort ( ) ; //清除资源 server.Close ( ) ; } catch { } ; if ( disposing ) { if ( components != null ) { components.Dispose ( ) ; } } base.Dispose ( disposing ) ;}至此,在上述步骤都正确完成,【UDP对时服务器端】项目的全部工作就完成了。图02【UDP对时服务器端】运行后的界面,在日志信息中记录了对时请求客户机的名称,发送对时数据的端口号以及客户端请求的时间:

图02:【UDP对时服务器端】项目的运行界面 图02:【UDP对时服务器端】项目的运行界面

17.并以下面代码替换Form.cs中由系统产生的InitializeComponent过程。

private void InitializeComponent ( ){this.button1 = new System.Windows.Forms.Button ( ) ;this.button2 = new System.Windows.Forms.Button ( ) ;this.textBox1 = new System.Windows.Forms.TextBox ( ) ;this.textBox2 = new System.Windows.Forms.TextBox ( ) ;this.label1 = new System.Windows.Forms.Label ( ) ;this.label2 = new System.Windows.Forms.Label ( ) ;this.label3 = new System.Windows.Forms.Label ( ) ;this.textBox3 = new System.Windows.Forms.TextBox ( ) ;this.SuspendLayout ( ) ;this.button1.FlatStyle = System.Windows.Forms.FlatStyle.Flat ;this.button1.Location = new System.Drawing.Point ( 128 , 128 ) ;this.button1.Name = "button1" ;this.button1.Size = new System.Drawing.Size ( 112 , 40 ) ;this.button1.TabIndex = 0 ;this.button1.Text = "获取" ;this.button1.Click += new System.EventHandler ( this.button1_Click ) ;this.button2.FlatStyle = System.Windows.Forms.FlatStyle.Flat ;this.button2.Location = new System.Drawing.Point ( 128 , 184 ) ;this.button2.Name = "button2" ;this.button2.Size = new System.Drawing.Size ( 112 , 40 ) ;this.button2.TabIndex = 1 ;this.button2.Text = "对时" ;this.button2.Click += new System.EventHandler ( this.button2_Click ) ;this.textBox1.Location = new System.Drawing.Point ( 120 , 56 ) ;this.textBox1.Name = "textBox1" ;this.textBox1.Size = new System.Drawing.Size ( 200 , 21 ) ;this.textBox1.TabIndex = 2 ;this.textBox1.Text = "" ;this.textBox2.Location = new System.Drawing.Point ( 120 , 88 ) ;this.textBox2.Name = "textBox2" ;this.textBox2.Size = new System.Drawing.Size ( 200 , 21 ) ;this.textBox2.TabIndex = 3 ;this.textBox2.Text = "" ;this.label1.Location = new System.Drawing.Point ( 48 , 56 ) ;this.label1.Name = "label1" ;this.label1.TabIndex = 4 ;this.label1.Text = "本地时间:" ;this.label2.Location = new System.Drawing.Point ( 40 , 88 ) ;this.label2.Name = "label2" ;this.label2.Size = new System.Drawing.Size ( 88 , 24 ) ;this.label2.TabIndex = 5 ;this.label2.Text = "服务器时间:" ;this.label3.Location = new System.Drawing.Point ( 16 , 24 ) ;this.label3.Name = "label3" ;this.label3.Size = new System.Drawing.Size ( 112 , 23 ) ;this.label3.TabIndex = 6 ;this.label3.Text = "设定服务器地址:" ;this.textBox3.Location = new System.Drawing.Point ( 120 , 24 ) ;this.textBox3.Name = "textBox3" ;this.textBox3.Size = new System.Drawing.Size ( 200 , 21 ) ;this.textBox3.TabIndex = 7 ;this.textBox3.Text = "" ;this.AutoScaleBaseSize = new System.Drawing.Size ( 6 , 14 ) ;this.ClientSize = new System.Drawing.Size ( 352 , 245 ) ;this.Controls.AddRange ( new System.Windows.Forms.Control[] { this.textBox3 , this.textBox2 , this.textBox1 , this.button2 , this.button1 , this.label1 , this.label2 , this.label3} ) ;this.MaximizeBox = false ;this.Name = "Form1" ;this.Text = "UDP对时客户端" ;this.ResumeLayout ( false ) ;}至此【UDP对时客户端】项目的界面设计和程序功能实现的前期工作就基本完成了,其设计界面如图03所示:

图03:【UDP对时客户端】项目的设计界面 图03:【UDP对时客户端】项目的设计界面

18.在Form1.cs中的InitializeComponent过程之后,添加下列代码,下列代码的功能是在程序中导入WinAPI函数——SetSystemTime,这个函数位于文件Kernel32.dll。程序就是通过此函数来更正系统时间的。

[ DllImport ( "Kernel32.dll" )]private static extern bool SetSystemTime ( SystemTime time ) ;//引入API函数19.并把它添加到在导入WinAPI函数代码之后,再添加下列代码,下列代码是定义“start_client”过程。此过程的功能是向服务器端传送对时请求,并获取从服务器端反馈来的时间日期数据。

{ client = new UdpClient ( port ) ; IPAddress a = IPAddress.Parse ( "127001" ) ; receivePoint = new IPEndPoint ( a , port ) ; IPAddress HostIP ; bool continueLoop = true ; while ( continueLoop ) { string hostName = Dns.GetHostName ( ) ; System.Text.ASCIIEncoding encode = new System.Text.ASCIIEncoding ( ) ; //定义发送到服务器端的请求信息 //请求信息是一个字符串,为客户端名称和接收服务器反馈信息的端口号组成的字符串 string sendString = hostName + "/" + port.ToString ( ) ; byte[] sendData = encode.GetBytes ( sendString ) ; //判断使用者输入的是IP地址还是计算机名称 try { HostIP = IPAddress.Parse ( textBox3.Text ) ; } catch { //如果输入的是计算机名称,则按照执行下列代码。 //发送请求信息 client.Send ( sendData , sendData. Length , textBox3.Text , 8080 ) ; //接收来自服务器端的信息 byte[] recData = client.Receive ( ref receivePoint ) ; timeString = encode.GetString ( recData ) ; client.Close ( ) ; continueLoop=false ; return ; } //输入的是IP地址,则执行下列代码 IPEndPoint host = new IPEndPoint ( HostIP ,8080 ) ; //发送请求信息 client.Send ( sendData , sendData.Length , host ) ; //接收来自服务器端的信息 byte[] recData1 = client.Receive ( ref receivePoint ) ; //获取服务器端的时间和日期 timeString = encode.GetString ( recData1 ) ; client.Close ( ) ; //退出循环 continueLoop=false ; }}如果“start_client”过程正确调用,就把服务器端的时间和日期保存到timeString字符串中了。

20.用下列代码替换Form1.cs中button1的“Click”事件的处理代码。下列代码的功能是调用“start_client”过程,获取并显示服务器端程序的时间和日期信息。

private void button1_Click ( object sender , System.EventArgs e ){ start_client ( ) ; textBox1.Text = DateTime.Now.ToString ( ) ; //显示客户端当前时间和日期 textBox2.Text = timeString ; //显示服务器当前时间和日期}21.用下列代码替换Form1.cs中button2的“Click”事件对应的处理代码。下列代码的功能是根据获取的服务器时间和日期数据来更正客户端时间和日期。

private void button2_Click ( object sender , System.EventArgs e ){ start_client ( ) ; //把接收来的数据转换时间日期格式 try { temp = DateTime.Parse ( timeString ) ; } catch { MessageBox.Show ( "错误时间" ) ; return ; } //根据得到的时间日期,来定义时间、日期 SystemTime st= new SystemTime ( ) ; st.year= ( short )temp.Year ; st.Month= ( short )temp.Month ; st.DayOfWeek= ( short )temp.DayOfWeek ; st.Day= ( short )temp.Day ; st.Hour=Convert.ToInt16 ( temp.Hour ) ; if ( st.Hour>=12 ) { st.Hour-= ( short )8 ; } else if ( st.Hour >= 8 ) { st.Hour-= ( short )8 ; } else { st.Hour+= ( short )16 ; } st.Minute=Convert.ToInt16 ( temp.Minute ) ; st.Second=Convert.ToInt16 ( temp.Second ) ; st.Milliseconds=Convert.ToInt16 ( temp.Millisecond ) ; //修改本地端的时间和日期 if ( SetSystemTime ( st ) ) { MessageBox.Show ( DateTime.Now.ToString ( ) ,"修改成功" ) ; } else MessageBox.Show ( "不成功!" ,"不成功" ) ;}至此,在正确完成上述步骤,全部保存后,【网络对时客户端】项目的全部工作就完成了。 六.运行基于UDP协议网络对时系统,实现网络对时: 首先要确认确认网络对时系统中的服务器端程序已经运行和其IP地址或主机名。然后在客户机上运行网络对时系统中的客户端程序,在正确输入运行网络对时系统服务器端程序对应的主机名或者IP地址后,单击客户端程序中【获取】按钮,则在程序的文本框中显示服务器当前时间和日期和客户端当前的时间和日期。若发现二种存在差异,单击【对时】按钮,则将以服务器当前时间和日期来修正客户机的时间和日期。修改成功则弹出【修改成功】提示框,反之则弹出【不成功】提示框,图04是【UDP对时客户端】项目根据服务器端当前时间和日期信息成功更改本地时间和日期后的界面:

七.总结: 本文详细介绍了UDP协议,.Net FrameWork SDK提供给Visual C#用以操作UDP协议的主要类库,以及通过一个具体而使用的示例——实现一个网络对时系统,介绍在Visual C#实现UDP协议的具体方法和过程。UDP由于其自身的缺点注定在某些领域无法利用它,但在可以利用它的领域,UDP以其快捷、简单、实用的特点正在受到更多程序员的欢迎。尤其在现代,网络运行态势越来越好的情况下,可以预见的是UDP在网络中的应用情景将更广阔。希望本文的内容对您掌握用Visual C#编写基于UDP的网络应用程序有所帮助。

本文标签:实现协议

原文链接:https://www.xgfox.com/jsyd/926.html

本文版权:如无特别标注,本站文章均为原创。