迹忆客 专注技术分享

当前位置:主页 > 学无止境 > 编程语言 >

在 C# 中创建一个 UDP 服务器

作者:迹忆客 最近更新:2024/01/16 浏览次数:

本文将展示如何在 C# 中创建一个简单的 UDP 服务器。


C# 中创建一个 UDP 服务器

简单介绍一下背景,UDP 协议不需要与客户端建立连接。数据只是传输而不验证客户端是否接收到它。

这种类型的协议通常用于广播数据。由于 UDP 是无连接的,因此侦听器无需在线即可接收消息。

要使用 UDP 传输数据报,你需要知道托管服务的网络设备的网络地址和服务的 UDP 端口号。流行服务的端口号由 Internet 号码分配机构 (IANA) 定义;端口号的范围是 1,024 到 65,535,可以分配给不在 IANA 列表中的服务。

在基于 IP 的网络上,特殊的网络地址用于处理 UDP 广播消息。以下解释以 Internet 的 IP 版本 4 地址族为例。

通过设置主机标识的所有位,可以将广播定向到网络的指定部分。使用地址 192.168.1.255 向网络上所有 IP 地址以 192.168.1 开头的主机广播。

我们现在准备建立或创建一个套接字,设置我们的 UDP 协议,并立即开始通信。

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

这些将是用于设置服务器的库。这些库支持与网络相关的所有基本功能,例如构建套接字、处理 IPV4 地址等等。

public class SimpleUdpSrvr {
  public static void Main() {
    int recv;
    byte[] data = new byte[1024];
    IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9050);
    Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
  }
}

int recv 行创建一个整数类型的 recv 变量,其中包含客户端收到的字符串消息的字节数。

byte[] data = new byte[1024]; line 用于为每个包含 1024 个单元格的单元格创建一个名为 data 的字节大小的数组,也称为数组大小。该数组是在堆中动态创建的。

IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9050); 行告诉它为套接字创建一个 ipep 变量。传入的信息告诉它应该使用什么样的套接字。

IPEndPoint 类表示具有 IP 地址和端口号的网络端点;客户端需要此配置信息来连接我们的服务。传入的 IPAddress.Any 参数告诉服务器可以使用任何 IP 地址连接到 9050 端口号; ipep 变量也是动态创建的。

Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

这一行创建了一个 newsock 变量,一个我们将通过它进行通信的套接字。传入的参数告诉我们要创建什么样的套接字。

AddressFamily.InterNetwork 告诉我们我们需要本地 IP 地址。SocketType.Dgram 参数指出数据应该以数据报而不是数据包的形式流动。

最后,ProtocolType.Udp 参数告诉我们将使用的套接字的协议类型。现在,我们的套接字已创建。

newsock.Bind(ipep);
Console.WriteLine("Waiting for a client...");

IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
EndPoint Remote = (EndPoint)(sender);

到目前为止,我们已经在网络中创建了一个端点,以及一个用于通信的套接字,newsock.Bind(ipep); line 现在将帮助我们将端点绑定到套接字。

ipep 是一个变量,它包含关于我们端点的信息,并在我们的 newsock 对象的 bind() 函数中传递。

Console.WriteLine("Waiting for a client...");

此行在屏幕上打印服务器正在等待客户端发送任何消息。我们需要为将尝试与服务器通信的发送方创建另一个端点。

IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);

这一行创建了另一个端点,变量称为 sender。在它的 IPAddress.Any 中传递的参数告诉我们期待任何 IP 地址,而 0 意味着它是端口号的通配符,系统应该看到并找到任何合适的端口分配给我们。

EndPoint Remote = (EndPoint)(sender); 行用于查找发送者的 IP 地址并将其存储在 remote 变量中。

recv = newsock.ReceiveFrom(data, ref Remote);

Console.WriteLine("Message received from {0}:", Remote.ToString());
Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));

我们在程序开始时创建的 recv 变量现在用于 recv = newsock.ReceiveFrom(data, ref Remote); 线。我们使用之前创建的套接字 newsockReceive() 函数,并且当前接收我们当时在套接字中的所有数据。

传递 Receive() 函数的参数告诉在哪里存储数据以及应该存储或预期谁的数据。data 参数是被传递的字节大小数组,数据将被写入数据数组。

ref Remote 参数告诉 IP 地址发送了数据,该函数将返回从该套接字获取的字节数并将其存储到 recv 变量中。

Console.WriteLine("Message received from {0}:", Remote.ToString());

此行在屏幕上写入通过套接字发送数据的客户端的 IP 地址。传递的参数 Remote.ToString() 将十进制数字转换为 ASCII 字符,而 remote 变量是引用客户端的第二个端点。

Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));

这一行将实际数据写入屏幕。通过套接字发送的数据为原始形式,应转换为 ASCII 字符才能读取。

Encoding.ASCII.GetString(data, 0, recv) 行从作为参数传递的 data 变量中获取数据,recv 参数(包含客户端发送的字节数)告诉从屏幕上的 data 变量中写入这么多字节。

string welcome = "Welcome to my test server";
data = Encoding.ASCII.GetBytes(welcome);
newsock.SendTo(data, data.Length, SocketFlags.None, Remote);

string welcome = "欢迎来到我的测试服务器"; 行用欢迎来到我的测试服务器文本初始化欢迎字符串变量。

data = Encoding.ASCII.GetBytes(welcome); line 将 welcome 变量作为 Encoding.ASCII.GetBytes() 函数中的参数并将其转换为原始形式,以便准备好通过另一端的套接字发送。

newsock.SendTo(data, data.Length, SocketFlags.None, Remote);

这一行通过我们之前创建的套接字 newsock 发送数据并使用 Send() 函数。它需要的参数是:包含要发送的原始数据形式的 data 变量,data.Length 参数告诉在套接字上写入多少字节,因为数据的长度等于字节数, SocketFlags.None 参数告诉我们将所有标志保持为零,标志是指示符,每个标志都有其含义。

Remote 变量参数告诉我们要将数据发送到的客户端,因为 Remote 变量存储客户端的 IP 地址和端口号。

while (true) {
  data = new byte[1024];
  recv = newsock.ReceiveFrom(data, ref Remote);

  Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));
  newsock.SendTo(data, recv, SocketFlags.None, Remote);
}

while(true) 行表明它是一个无限循环,并且它的所有语句都将无限运行。数据 = 新字节 [1024]; 行在执行时创建一个长度为 1024 的新字节大小数组。

recv = newsock.ReceiveFrom(data, ref Remote); line 从客户端接收数据并将其保存到数据数组中。

Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv)); 将数据写入屏幕。

newsock.SendTo(data, recv, SocketFlags.None, Remote); 行将服务器从它收到的相同数据发送回客户端。

之后,服务器将再次停止并等待客户端,客户端发送给服务器的任何内容都会以相同的消息进行响应。该服务器将永远不会终止,除非它崩溃或用户手动停止它。

现在,当我们学习了如何在 C# 中创建 UDP 服务器及其基本功能后,我们可以添加更多功能并根据我们的要求制作服务器。

完整的源代码:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

public class SimpleUdpSrvr {
  public static void Main() {
    int recv;
    byte[] data = new byte[1024];
    IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9050);

    Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

    newsock.Bind(ipep);
    Console.WriteLine("Waiting for a client...");

    IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
    EndPoint Remote = (EndPoint)(sender);

    recv = newsock.ReceiveFrom(data, ref Remote);

    Console.WriteLine("Message received from {0}:", Remote.ToString());
    Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));

    string welcome = "Welcome to my test server";
    data = Encoding.ASCII.GetBytes(welcome);
    newsock.SendTo(data, data.Length, SocketFlags.None, Remote);
    while (true) {
      data = new byte[1024];
      recv = newsock.ReceiveFrom(data, ref Remote);

      Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));
      newsock.SendTo(data, recv, SocketFlags.None, Remote);
    }
  }
}

上一篇:在 C# 中创建石头剪刀布游戏

下一篇:没有了

转载请发邮件至 1244347461@qq.com 进行申请,经作者同意之后,转载请以链接形式注明出处

本文地址:

相关文章

C# 中的 LINQ 分组

发布时间:2024/01/20 浏览次数:51 分类:编程语言

LINQ 中的 group by 用于按 C# 中的某个公共值对对象序列进行分组 C# 中的 LINQ 分组 LINQ 将类似 SQL 的查询功能与 C# 中的数据结构集成在一起。

使用 C# 在 LINQ 查询中按多列分组

发布时间:2024/01/20 浏览次数:167 分类:编程语言

这是一篇关于 LINQ 查询的使用以及我们如何使用 LINQ 查询按列分组的文章。本文简要介绍了使用 C# 进行的 LINQ 查询。此外,它还讨论了如何使用 LINQ 查询按多列对结果进行分组。

在 C# 中捕获多个异常

发布时间:2024/01/20 浏览次数:135 分类:编程语言

有两种主要方法可用于捕获 C# 中的多个异常,即 Exception 类和 catch 子句中的 if 语句。使用 C# 中的 Exception 类捕获多个异常 Exception 类用于表示 C# 中的一般异常。

C# 中为无效参数或参数引发的异常类型

发布时间:2024/01/20 浏览次数:71 分类:编程语言

本教程将教你如何在 C# 中为无效参数或参数抛出不同类型的异常。异常提供有关 C# 程序中的运行时错误或预期不会发生或违反系统/应用程序约束的条件的信息。在本教程中,你将学习与无效参

C# 中的异常列表

发布时间:2024/01/20 浏览次数:128 分类:编程语言

我们将查看本文中可能引发的 C# 异常。System Exception 类是 C# 编程语言中预定义的异常类,可用于编程。选择代码中可能出现的异常并将其插入到适当的 catch 块中。

C# 中的树形数据结构

发布时间:2024/01/20 浏览次数:73 分类:编程语言

C# 中的树是本文讨论的主题。一种以树的形式组织起来的层次数据称为树数据结构。C# 中的树将是本文讨论的主题。数据结构是我们需要知道的第一件事。

C# 中的 lock 语句

发布时间:2024/01/20 浏览次数:166 分类:编程语言

C# 中 lock 语句指定的代码部分不能被多个线程同时访问。C# 中的 lock 语句 lock(obj) 语句规定,在 C# 中,下面这段代码不能被多个线程同时访问。

扫一扫阅读全部技术教程

社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

最新推荐

教程更新

热门标签

扫码一下
查看教程更方便