如何在 .NET 应用程序之间轻松交换数据
本文介绍了一种通过 UDP 协议进行无连接通信的简单方法。
引言
我们可以选择多种解决方案来交换两个(或更多)不同应用程序之间的数据:Remoting、命名管道、TCP 客户端-服务器等。但是,在所有这些技术中,通信应用程序必须在交换数据时连接,并且您的程序必须始终为突发连接断开做好准备。 对于简单的目的来说,这太复杂了。
经过几天的搜索,我找到了最简单的数据交换方法。 此解决方案使用 UdpClient
类来发送和接收数据。
背景
UdpClient
在 System.Net.Sockets
命名空间中定义。 它允许将数据发送到任何主机和任何端口,并从任何其他主机接收数据。 当应用程序发送数据时,它发送到 HOST 和 PORT,而不是发送到第二个应用程序。 此外,第二个应用程序甚至可能没有运行! 这两个应用程序之间没有连接,这是此解决方案的最佳特性。
让我们看看它是如何工作的。
首先,您需要在程序中初始化一个 UdpClient
对象。 UdpClient
类有很多构造函数。 所有这些都需要“知道”您选择的网络协议以及将用于接收数据的端口。
int port=65000
UdpClient u=new UdpClient(port, AddressFamily.InterNetwork);
正如您在上面的列表中看到的,我使用任意端口号 65000 初始化了对象 u
,第二个参数指向合适的网络协议。
现在,应用程序可以读取从网络中同一台或什至是远程机器上运行的其他程序发送到端口 65000 的所有数据。
要读取(接收数据),您可以使用这段代码
if (u.Available > 0)
{
IPEndPoint e = new IPEndPoint(IPAddress.Any, 0);
byte[] b = u.Receive(ref e);
string readData = ASCIIEncoding.UTF32.GetString(b);
}
首先,我检查端口上准备好读取的字节数。 您可以从 UdpCleint
的 Available
属性获取此值。 因此,如果“可用”字节的数量大于零,则使用 Receive
方法读取这些字节。 方法 Receive
需要引用指向发送数据的主机的 IP 的 IPEndPoint
对象。 它还需要一个发送数据的端口。 如您所见,我使用 IpAdress.Any
来创建 IPEndPoint
。 这意味着我想读取由任何主机发送的数据。 我还使用 0 作为第二个参数 - 这意味着我想读取从任何端口发送的数据。 Receive
方法具有“阻塞”行为; 这意味着它会等待直到端口上有可用的数据。 这就是为什么我在调用 Receive
方法之前检查 u.Available>0
条件的原因。
至于发送数据,它比读取更容易。 看一下下面的例子
int port=65001
string host="localhost";
UdpClient u1 = new UdpClient();
u1.Connect(host, p);
u1.Send(ASCIIEncoding.UTF32.GetBytes(s), ASCIIEncoding.UTF32.GetByteCount(s));
u1.Close(); // release all recources allocated by UdpClient
我使用无参数构造函数创建一个新的 UdpClient
。 接下来,我尝试连接到另一个主机和端口。 在我的示例中,主机是“localhost”; 这意味着我要向其发送数据的应用程序在同一台机器上运行。 我再次重复:当我使用 Connect 方法时,这并不意味着我与第二个应用程序连接,而只是与主机和端口连接。
请注意,在示例中,我使用端口 65001,因此我不会将数据发送给自己(即 65000),而是发送到另一个可以在此端口读取的应用程序。
现在我们可以读写了。 假设我们有两个应用程序:App1 和 App2,它们都在同一台机器(localhost)上运行。
第一个包含一个初始化为如下的 UdpClient
对象
UdpClient u=new UdpClient(65000, AddressFamily.InterNetwork); // App1
第二个
UdpClient u=new UdpClient(65001, AddressFamily.InterNetwork); // App2
现在 App1 使用以下代码将数据发送到 App2
string s = "This is app1 is anybody there?"; // data to send
UdpClient u1 = new UdpClient();
u1.Connect("localhost", 65001);
u1.Send(ASCIIEncoding.UTF32.GetBytes(s), ASCIIEncoding.UTF32.GetByteCount(s));
App2 接收数据
if (u.Available > 0) // default port for u is 65001
{
IPEndPoint e = new IPEndPoint(IPAddress.Any, 0);
byte[] b = u.Receive(ref e);
string readData = ASCIIEncoding.UTF32.GetString(b);
}
并回答(向 App1 发送消息)
string s = "App2 here howdy"; // data to send
UdpClient u1 = new UdpClient();
u1.Connect("localhost", 65000); // sending to 65000 i.e. App1
u1.Send(ASCIIEncoding.UTF32.GetBytes(s), ASCIIEncoding.UTF32.GetByteCount(s));
使用代码
下面,我放置了一个完整的库清单,可以将其编译为 DLL。 它是上面列出的代码的简单包装器。
using System.Net;
using System.Net.Sockets;
namespace UDP
{
public class SimpleUDP
{
UdpClient u;
public SimpleUDP(int port)
{
u = new UdpClient(port, AddressFamily.InterNetwork);
}
public void Write(string s, string host, int p)
{
UdpClient u1 = new UdpClient();
u1.Connect(host, p);
u1.Send(ASCIIEncoding.UTF32.GetBytes(s), ASCIIEncoding.UTF32.GetByteCount(s));
u1.Close(); // release all recources allocated by UdpClient
}
public string Read()
{
if (u.Available > 0)
{
IPEndPoint e = new IPEndPoint(IPAddress.Any, 0);
byte[] b = u.Receive(ref e);
return ASCIIEncoding.UTF32.GetString(b);
}
return "";
}
public void Close()
{
u.Close();
u = null;
}
}
}
您可以在两个或多个应用程序中使用 SimpleUDP
类。 这很容易。
App1 使用构造函数和两个方法来写入 App2 并从中读取。
SimpleUDP u=new SimpleUDP(65000)
// ...
string s = u.Read();
// ...
u.Write("How do you do App2");
对于 App2,我们使用类似的代码进行读写
SimpleUDP u=new SimpleUDP(65001) // App2 reads data at port 65001
// ...
string s = u.Read();
// ...
u.Write("Welcome App1");