使用UDP非连线式发送接收数据(聊天室模式)
UDP非连线式通讯在.net中可以很方便的实现出来。
大致原理:
使用UdpClient通过指定远程机的IP和端口发送数据到远程机,实现起来很简单,主要代码如下:
System.Net.Sockets.UdpClient udp = new System.Net.Sockets.UdpClient();
udp.Connect("192.168.0.102", 12000); //连接到指定主机名(我在这里直接使用IP)和端口的远程机
//将文本框的字符串内容转换为字节数组后存储在字节数组b中
byte[] b=System.Text.Encoding.UTF8.GetBytes(textBox2.Text);
try
{
//执行发送
udp.Send(b,b.Length);
MessageBox.Show("发送成功!");
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
//关闭UPDCLIENT
udp.Close();
接收的时候同样也很方便,首先定义一个全局的udpclient但这时候不要创建实例。当FORMLOAD的时候创建udpclient实例,创建实例时指定本地的通讯端口(该端口就是发送的时候做指定的远程机端口),之后需要创建一个新的线程来执行数据的接收,这一点非常重要,由于udpclient是非连线的,因此接收端在创建好一个udpclient的并执行接收后,接收的线程将一直在udpclient所指定的端口等待发送过来的数据,这时候如果使用和应用程序同样的现成将造成应用程序线程看上去死掉了,所以必须另开一个线程来执行等待数据的工作。
接收段代码如下:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
namespace SmartClient
{
///<summary>
/// Udpclient 的摘要说明。
///</summary>
public class Udpclient : System.Windows.Forms.Form
{
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Label label1;
private System.Net.Sockets.UdpClient udp;//定义一个udpclient
private System.Threading.Thread t; //定义一个线程
///<summary>
/// 必需的设计器变量。
///</summary>
private System.ComponentModel.Container components = null;
public Udpclient()
{
//
// Windows 窗体设计器支持所必需的
//
InitializeComponent();
//
// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
//
}
///<summary>
/// 清理所有正在使用的资源。
///</summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows 窗体设计器生成的代码
///<summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
///</summary>
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(96, 208);
this.button1.Name = "button1";
this.button1.TabIndex = 0;
this.button1.Text = "关闭";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// label1
//
this.label1.Location = new System.Drawing.Point(8, 8);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(272, 176);
this.label1.TabIndex = 1;
//
// Udpclient
//
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
this.ClientSize = new System.Drawing.Size(292, 266);
this.Controls.Add(this.label1);
this.Controls.Add(this.button1);
this.Name = "Udpclient";
this.Text = "Udpclient";
this.Load += new System.EventHandler(this.Udpclient_Load);
this.ResumeLayout(false);
}
#endregion
private void button1_Click(object sender, System.EventArgs e)
{
//当点击关闭按钮的时候关闭udpclient并终止数据接收的线程,然后关闭窗体
//由于 通常每个套接字地址(协议/网络地址/端口)只允许使用一次,
//所以在关闭窗体前必须关闭udpclient和数据接收的线程
udp.Close();
t.Abort();
this.Hide();
this.Close();
}
private void Udpclient_Load(object sender, System.EventArgs e)
{
//创建该udpclient的实例
udp = new System.Net.Sockets.UdpClient(12000);
//创建线程实例,并将该线程绑定一个例程,当该线程启动的时候执行这个例程(在这里我的例程名是‘listen’)
t = new System.Threading.Thread(new System.Threading.ThreadStart(listen));
//将线程转为后台运行(当托管线程关闭的时候此现成也关闭)
t.IsBackground=true;
t.IsBackground=true;
//启动这个线程
t.Start();
}
//当前文中的线程启动时执行
void listen()
{
//线程等待2秒
System.Threading.Thread.Sleep(2000);// 确保 client2 正在接收
//创建远程主机网络端点(这里未明确指定,表示任何远程机端点)
System.Net.IPEndPoint ep =new System.Net.IPEndPoint(System.Net.IPAddress.Any,0);
//循环的执行接收任务
//由于udp是非连接式的,
//所以需要一直让udpclient执行receive方法接收数据
//因此使用一个不终止的循环来执行receive方法
while(true)
{
//调用receive方法接收数据,将接收到的字节数组转换为字符串后显示到label中
label1.Text = System.Text.Encoding.UTF8.GetString(udp.Receive(ref ep));
}
}
}
}