C# System.Net.IPEndPoint 使用详解

总目录


前言

System.Net.IPEndPoint 是 .NET 中表示网络通信端点的核心类,用于表示网络通信中的端点(IP 地址 + 端口号)。无论是 TCP 服务器、UDP 客户端还是网络工具开发,IPEndPoint 都是不可或缺的组件。本文将详细介绍 IPEndPoint 的使用方法和常见场景。


一、什么是 IPEndPoint

1. 定义

IPEndPoint 继承自 EndPoint 类,是 System.Net 命名空间中的一个类,用于表示网络通信中的端点(IP 地址 + 端口号)。它是 Socket 编程、Web 服务交互等场景的核心组件。

2. 组成

IPEndPoint 由以下两部分组成:

  • IP 地址:标识网络上的设备。
  • 端口号:标识设备上的服务或应用程序。

在 C# 中,IPEndPoint 是网络通信的核心,因为它定义了通信的源和目标地址。

3. IPEndPoint 的核心作用

IPEndPoint 类的主要作用是将 IP 地址端口号 组合为一个逻辑端点,用于标识网络通信的目标或来源。例如:

  • TCP 服务器:绑定到本地端口监听连接。
  • UDP 客户端:指定发送数据的目标地址和端口。
  • 网络工具:解析或生成网络配置中的端点信息。

二、基本用法

1. IPEndPoint 的构造方法

IPEndPoint 提供了多种构造方法,可以根据需要选择合适的方式创建对象。

1)使用构造函数

csharp 复制代码
public IPEndPoint(long address, int port);
public IPEndPoint(IPAddress address, int port);
▶ 使用 IP 地址和端口号
csharp 复制代码
IPAddress ipAddress = IPAddress.Parse("192.168.1.1");
int port = 8080;
IPEndPoint endPoint = new IPEndPoint(ipAddress, port);
▶ 使用整数和端口
csharp 复制代码
long address = 0x2414188f; // 对应 IPv4 地址 143.24.20.36  
IPEndPoint endpoint = new IPEndPoint(address, 80);
Console.WriteLine(endpoint.ToString()); //输出:143.24.20.36:80

注意 :长整型需按大端序(网络字节序)转换,建议优先使用 IPAddress.Parse

csharp 复制代码
// 示例:创建 IPv4 端点
IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse("192.168.1.100"), 8080);

// 示例:创建 IPv6 端点
IPEndPoint ipv6Endpoint = new IPEndPoint(IPAddress.Parse("2001:db8::1"), 53);

2)使用 Parse 和 TryParse 解析字符串

通过字符串直接创建 IPEndPoint,需注意格式要求:

  • IPv4 格式IP:Port(如 "192.168.1.100:8080")。
  • IPv6 格式[IPv6地址]:Port(如 "[2001:db8::1]:53")。
Parse 方法
csharp 复制代码
// 成功解析
IPEndPoint endpoint = IPEndPoint.Parse("127.0.0.1:80"); 
Console.WriteLine(endpoint);	//输出:127.0.0.1:80

// IPv6 需要方括号
IPEndPoint ipv6Endpoint = IPEndPoint.Parse("[2001:db8::1]:53");
Console.WriteLine(ipv6Endpoint );	//输出:[2001:db8::1]:53
TryParse 方法(推荐)

避免异常,返回布尔值表示是否成功:

csharp 复制代码
if (IPEndPoint.TryParse("localhost:8080", out IPEndPoint? endpoint))
{
    Console.WriteLine($"成功解析端点:{endpoint}");
}
else
{
    Console.WriteLine("解析失败");
}
▶ 注意事项
  • 无效地址问题 :若输入字符串可解析为 Int64Parse 会将其视为 IP 地址(如 "1" 会被解析为 0.0.0.1)。需确保输入符合点分十进制格式。
  • 端口范围 :端口号必须在 0-65535 之间。

2. 主要字段与属性

IPEndPoint 提供了一些常用的属性,用于获取和设置端点的信息。

成员 类型 说明
MaxPort const int 端口最大值(65535),用于验证端口合法性
MinPort const int 端口最小值(0),0 表示自动分配可用端口
Address IPAddress 获取/设置终结点 IP 地址(支持运行时动态修改)
Port int 获取/设置终结点端口号(需在 0-65535 范围内)
AddressFamily AddressFamily 标识地址族(IPv4/IPv6)

使用示例:

csharp 复制代码
class Program
{
    static void Main()
    {
        IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("192.168.1.1"), 8080);
        Console.WriteLine($"IP Address: {endPoint.Address}");   // IP Address: 192.168.1.1
        Console.WriteLine($"Port: {endPoint.Port}");    // Port: 8080
        // 修改 IP 地址和端口号
        endPoint.Address = IPAddress.Parse("192.168.1.2");
        endPoint.Port = 8081;
        Console.WriteLine($"Modified IP Address: {endPoint.Address}");  // Modified IP Address: 192.168.1.2
        Console.WriteLine($"Modified Port: {endPoint.Port}");   //Modified Port: 8081

        // 获取端口最大最小值
        Console.WriteLine($"MaxPort: {IPEndPoint.MaxPort}");    // MaxPort: 65535
        Console.WriteLine($"MinPort: {IPEndPoint.MinPort}");    // MinPort: 0
    }
}

3. 序列化与反序列化

IPEndPoint 可通过 Serialize 方法转换为 SocketAddress,用于低级网络操作:

csharp 复制代码
class Program
{
    static void Main()
    {
        IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("192.168.1.1"), 8080);
        SocketAddress socketAddress= endPoint.Serialize();
        Console.WriteLine(socketAddress);

        Console.WriteLine(endPoint.Create(socketAddress));
    }
}

三、典型应用场景

1. 用于 Socket 通信

IPEndPointSocket 通信中常用的类,用于绑定本地端点或连接远程端点。

▶ 绑定本地端点
csharp 复制代码
using System.Net;
using System.Net.Sockets;

// 创建 Socket
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

// 创建本地端点
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 8080);

// 绑定本地端点
socket.Bind(localEndPoint);

IPAddress.Any 表示绑定本机所有可用 IP

▶ 连接远程端点
csharp 复制代码
// 创建远程端点
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse("192.168.1.1"), 8080);

// 连接远程端点
socket.Connect(remoteEndPoint);

2. 用于 TcpListener

TcpListener 是一个常用的类,用于监听传入的 TCP 连接请求。IPEndPoint 可以用来指定监听的地址和端口。

csharp 复制代码
using System.Net;
using System.Net.Sockets;

// 创建监听端点
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 8080);

// 创建 TcpListener
TcpListener listener = new TcpListener(endPoint);

// 开始监听
listener.Start();

Console.WriteLine("等待连接...");
TcpClient client = listener.AcceptTcpClient();
Console.WriteLine("客户端已连接");

3. 用于 UdpClient

UdpClient 是一个用于 UDP 通信的类,IPEndPoint 可以用来发送和接收数据。

▶ 发送数据
csharp 复制代码
using System.Net;
using System.Net.Sockets;

// 创建远程端点
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse("192.168.1.1"), 8080);

// 创建 UdpClient
UdpClient udpClient = new UdpClient();

// 发送数据
byte[] data = Encoding.UTF8.GetBytes("Hello, World!");
udpClient.Send(data, data.Length, remoteEndPoint);
▶ 接收数据
csharp 复制代码
using System.Net;
using System.Net.Sockets;

// 创建本地端点
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 8080);

// 创建 UdpClient 并绑定本地端点
UdpClient udpClient = new UdpClient(localEndPoint);

Console.WriteLine("等待数据...");
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
byte[] data = udpClient.Receive(ref remoteEndPoint);

Console.WriteLine($"收到数据: {Encoding.UTF8.GetString(data)}");
Console.WriteLine($"来自: {remoteEndPoint.Address}:{remoteEndPoint.Port}");

4. 实例应用

下面通过一个简单的服务器和客户端示例,演示如何使用 IPEndPoint 类进行网络通信。

▶ 服务器端
csharp 复制代码
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
public class TcpServer
{
    public static void Main()
    {
        // 创建一个 TcpListener,绑定到本地 IP 地址和端口号
        IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
        int port = 8080;
        TcpListener listener = new TcpListener(new IPEndPoint(ipAddress, port));
        // 开始监听
        listener.Start();
        Console.WriteLine("服务器已启动,等待客户端连接...");
        // 接受客户端连接
        TcpClient client = listener.AcceptTcpClient();
        Console.WriteLine("客户端已连接。");
        // 获取网络流
        NetworkStream stream = client.GetStream();
        // 接收数据
        byte[] buffer = new byte[1024];
        int bytesRead = stream.Read(buffer, 0, buffer.Length);
        string dataReceived = Encoding.ASCII.GetString(buffer, 0, bytesRead);
        Console.WriteLine($"接收到的数据: {dataReceived}");
        // 发送数据
        string response = "Hello from server!";
        byte[] responseBytes = Encoding.ASCII.GetBytes(response);
        stream.Write(responseBytes, 0, responseBytes.Length);
        // 关闭连接
        stream.Close();
        client.Close();
        listener.Stop();
        Console.WriteLine("连接已关闭。");
    }
}
▶ 客户端
csharp 复制代码
using System;
using System.Net.Sockets;
using System.Text;
public class TcpClientApp
{
    public static void Main()
    {
        // 创建一个 TcpClient,连接到服务器的 IP 地址和端口号
        string serverIp = "127.0.0.1";
        int port = 8080;
        TcpClient client = new TcpClient(serverIp, port);
        Console.WriteLine("已连接到服务器。");
        // 获取网络流
        NetworkStream stream = client.GetStream();
        // 发送数据
        string message = "Hello from client!";
        byte[] messageBytes = Encoding.ASCII.GetBytes(message);
        stream.Write(messageBytes, 0, messageBytes.Length);
        Console.WriteLine($"发送的数据: {message}");
        // 接收数据
        byte[] buffer = new byte[1024];
        int bytesRead = stream.Read(buffer, 0, buffer.Length);
        string response = Encoding.ASCII.GetString(buffer, 0, bytesRead);
        Console.WriteLine($"从服务器接收到的数据: {response}");
        // 关闭连接
        stream.Close();
        client.Close();
        Console.WriteLine("连接已关闭。");
    }
}

四、常见问题与解决方案

1. IPv6 地址解析失败

原因:未使用方括号包裹 IPv6 地址。

csharp 复制代码
// 错误写法(缺少方括号)
IPEndPoint.Parse("2001:db8::1:53"); // 抛出异常

// 正确写法
IPEndPoint.Parse("[2001:db8::1]:53");

2. 端口超出范围

csharp 复制代码
// 端口号 70000 超出最大值 65535
var invalidEndpoint = new IPEndPoint(IPAddress.Loopback, 70000); // 抛出 ArgumentOutOfRangeException

端口合法性验证

csharp 复制代码
public static bool ValidatePort(int port)  
{  
    return port >= IPEndPoint.MinPort && port <= IPEndPoint.MaxPort;  
}  

// 使用示例  
if (!ValidatePort(70000))  
    throw new ArgumentOutOfRangeException("端口超出合法范围");  

3. 动态获取本地 IP 地址

csharp 复制代码
// 获取本机所有 IPv4 地址
var localIPs = Dns.GetHostEntry(Dns.GetHostName())
    .AddressList
    .Where(ip => ip.AddressFamily == AddressFamily.InterNetwork);

4. 异常处理策略

常见异常类型

  • ArgumentOutOfRangeException:端口号超出 0-65535 范围
  • ArgumentNullException:传入的 IPAddressnull
  • SocketException:端口已被占用或权限不足

处理建议

csharp 复制代码
try  
{  
    var endpoint = new IPEndPoint(IPAddress.Parse("invalid.ip"), 80);  
}  
catch (FormatException ex)  
{  
    Console.WriteLine($"IP地址格式错误: {ex.Message}");  
}  
catch (ArgumentOutOfRangeException ex)  
{  
    Console.WriteLine($"端口号非法: {ex.Message}");  
}  

5. 跨平台与性能优化

1)IPv4/IPv6 双栈支持

csharp 复制代码
// 优先使用 IPv6 并兼容 IPv4  
IPEndPoint ep = new IPEndPoint(IPAddress.IPv6Any, 8080);  
Socket socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);  
socket.DualMode = true; // 启用双栈模式  

2)端点池缓存优化

csharp 复制代码
private static ConcurrentDictionary<string, IPEndPoint> _endpointCache = new();  

public static IPEndPoint GetCachedEndpoint(string ip, int port)  
{  
    string key = $"{ip}:{port}";  
    return _endpointCache.GetOrAdd(key, k =>  
    {  
        IPAddress address = IPAddress.Parse(ip);  
        return new IPEndPoint(address, port);  
    });  
}  

五、最佳实践

  1. 优先使用 TryParse:避免因无效字符串导致的异常。
  2. 明确 IPv4/IPv6 格式:IPv6 地址需用方括号包裹。
  3. 端口范围检查 :确保端口号在 0-65535 之间。
  4. 使用 IPAddress.AnyIPAddress.IPv6Any:服务器监听所有网络接口。

结语

回到目录页:C#/.NET 知识汇总

希望以上内容可以帮助到大家,如文中有不对之处,还请批评指正。


参考资料:

相关推荐
低头不见10 分钟前
tcp的粘包拆包问题,如何解决?
网络·网络协议·tcp/ip
SKYDROID云卓小助手1 小时前
三轴云台之相机技术篇
运维·服务器·网络·数码相机·音视频
yuzhangfeng4 小时前
【云计算物理网络】从传统网络到SDN:云计算的网络演进之路
网络·云计算
TDengine (老段)4 小时前
TDengine 中的关联查询
大数据·javascript·网络·物联网·时序数据库·tdengine·iotdb
zhu12893035565 小时前
网络安全的现状与防护措施
网络·安全·web安全
zhu12893035566 小时前
网络安全与防护策略
网络·安全·web安全
沫夕残雪6 小时前
HTTP,请求响应报头,以及抓包工具的讨论
网络·vscode·网络协议·http
π2706 小时前
爬虫:网络请求(通信)步骤,http和https协议
网络·爬虫
闪电麦坤957 小时前
C#:base 关键字
开发语言·c#
mingupup8 小时前
C#连接小智服务器并将音频解码播放过程记录
c#