基于UDP的通信模块

时间:2022-07-12 12:23:25

基于UDP的通信模块

摘要:程序间的通信是一个老生常谈的话题了,不论是聊天程序、还是文件传输程序,都离不开数据的传递。而现在,编写一个数据传输的程序也并不是什么难事。但是,许多程序员每次在编写一个新程序时,都在从零开始编写程序间的通信部分,这就让我们把大量时间浪费在重复劳动上。所以很有必要把我们已经做好的通信部分模块化,这样,以后再编写相关部分时,只需把以前编好模块应用到新的程序中即可。

关键词:UDP;模块化;C#;通信

中图分类号:TP393.07 文献标识码:A文章编号:1007-9599 (2010) 05-0000-02

Communication Module Based on UDP

Gao Hao,Yang Guang

(Sun Yat-sen University,Guangzhou510006,China)

Abstract:The communication between the program is a commonplace subject,either chat program,or file transfer procedure,is inseparable from the data transfer.And now,write a data transfer program is not so difficult However, when programmers writing a new program, they often code the communication modules from scratch.These make us waste time on repeated labor.So it is very necessary to modularize the communication part.When we code the relevant parts ,we can just apply the module to the new program.

Keyword:UDP;Modularization;C#;Comunication

一、概述:

接下来,将编写一个采用UDP协议的通信模块,它负责接受、发送和处理数据。它采用模块化的设计思想,可以处理诸如消息传送、文件传送等事务。

二、UDP模块的具体实现代码:

public partial class UDPSocket : Component

{

private int localPort = 11000;

private IPEndPoint ServerEndPoint = null; //定义网络端点

private UdpClient UDP_Server = new UdpClient(); //创建网络服务,也就是UDPSocket

private System.Threading.Thread thdUdp; //创建一个线程

public delegate void DataArrivalEventHandler(byte[] Data, IPAddress Ip,

int Port);

public event DataArrivalEventHandler DataArrival; //在控件中定义一个事件

private string localHost = "127.0.0.1";

private bool active = false;

public bool Active

{

get { return active; }

set

{ active = value;

if (active)

OpenSocket();

else

CloseSocket();

}

protected void Listener()

{

ServerEndPoint = new IPEndPoint(IPAddress.Any, localPort);

if (UDP_Server != null)

UDP_Server.Close();

UDP_Server = new UdpClient(localPort);//创建一个新的端口号

UDP_Server.Client.ReceiveBufferSize = 1000000000; //接收缓冲区大小

UDP_Server.Client.SendBufferSize = 1000000000;//发送缓冲区大小

thdUdp = new Thread(new ThreadStart(GetUDPData));

thdUdp.IsBackground = true;

thdUdp.Start();

}

private void GetUDPData() /

{

while (active)

{

//将获取的远程消息转换成二进制流

byte[] Data = UDP_Server.Receive(ref ServerEndPoint);

if (DataArrival != null) {

//利用当前控件的DataArrival事件将消息发给远程计算机

DataArrival(Data, ServerEndPoint.Address, ServerEndPoint.Port);

Thread.Sleep(50);

}

}

}

public void Send(.IPAddress Host, int Port, byte[] Data)

{

IPEndPoint server = new IPEndPoint(Host, Port);

UDP_Server.Send(Data, Data.Length, server);

}

private void OpenSocket()

{

Listener();

}

private void CloseSocket()

{

if (UDP_Server != null)

UDP_Server.Close();

if (thdUdp != null) //如果自定义线程被打开

{

Thread.Sleep(30); //睡眠主线程

thdUdp.Abort(); //关闭子线程

}

}

}

这样,一个基于UDP的通信模块就基本实现了,但是它还不具备任何实际的功能,既不能传送消息,也不能传送任何数据。接下来将为它实现简单的文件传输功能来说明它的使用方法。

三、简单文件传输功能的实现

该示例程序采用C/S架构设计。客户端和服务器端各采用一个UDPSocket来处理通讯方面的需求。DataArrival事件将负责处理客户端和服务器端的业务逻辑。当UDPSocket接收到数据时,将引发DataArrival事件,从而引发客户端和服务器端进行不同的处理。

服务器端代码:

private delegate void DataArrivaldelegate(byte[] Data, .IPAddress Ip, int Port);

private void udpSocket1_DataArrival(byte[] Data, .IPAddress Ip, int Port)

{

DataArrivaldelegate outdelegate = new DataArrivaldelegate(DataArrival);

this.BeginInvoke(outdelegate, new object[] { Data, Ip, Port });

}

private void DataArrival(byte[] Data, .IPAddress Ip, int Port)

{

udpSocket1.Send(Ip, Port,Data);

}

客户端代码:

接收文件

private void DataArrival(byte[] Data, .IPAddress Ip, int Port)

{

ClassMsg msg = new ClassSerializer().DeSerializeBinary((new System.IO.MemoryStream(Data))) as ClassMsg;

FileStream fileStream = null;

try

{

string filePath = Environment.CurrentDirectory + "\\" + msg.FileName;

if (File.Exists(filePath))

filePath = Environment.CurrentDirectory + "\\" + msg.msgID + msg.FileName;

fileStream = new FileStream(filePath, FileMode.Create);

fileStream.Write(msg.Data, 0, msg.Data.Length);

}

finally

{

fileStream.Close();

}

}

发送文件

private void tsSendFile_Click(object sender, EventArgs e)

{

if (openFileDialog1.ShowDialog() == DialogResult.OK)

{

IPAddress ip = IPAddress.Parse(Publec_Class.ServerIP);

string port = Publec_Class.ServerPort;

FileStream fileStream = new FileStream(openFileDialog1.FileName, FileMode.Open, FileAccess.Read);

MemoryStream memStream = new MemoryStream();

int b = fileStream.ReadByte();

while (b != -1)

{

memStream.WriteByte((byte)b);

b = fileStream.ReadByte();

}

byte[] data = memStream.ToArray();

ClassMsg msg = new ClassMsg();

msg.Data = data;

msg.msgID = Guid.NewGuid().ToString();

msg.FileName = openFileDialog1.SafeFileName;

udpsocket.Send(ip, Convert.ToInt32(port),

new ClassSerializer().SerializeBinary(msg).ToArray());

}

}

这样,一个简单的文件传输功能就完成了,虽然这个示例里面没有把传输文件的大小等因素考虑在内,但是,作为一个示例来说,也足够清晰了。当然,我们也可以对这个示例进行进一步的扩充以实现更为强大功能。

四、总结

编写比较大型的软件时,直接从头开始开发耗费人力物力。通过重用以前的代码,可以快速高效的开发程序。而为了进行代码的重用,我们需要在编写程序时注意对软件进行模块化。每个模块应该是自治的,它隐藏具体的实现,只提供程序的接口。这样有利于对错误的排查、软件的维护和升级。

本文通过一个UDP通信模块的示例程序,展示了模块化编程的优点。之后通过一个示例程序,演示了该模块的用法。但是此模块的应用并不仅仅局限于此,它还能用于大部分的数据传输任务,这一切将有待于读者去发掘。

作者简介:

高浩(1990-),男,山东省巨野县人,单位全称:中山大学,学历:本科在读,研究方向:.net平台

杨光(1990-),男,山东省聊城市人,单位全称:中山大学学历:本科在读,研究方向:.net平台

上一篇:通信企业内部营销 下一篇:光通信网承载业务分析