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)使用构造函数

public IPEndPoint(long address, int port);
public IPEndPoint(IPAddress address, int port);
▶ 使用 IP 地址和端口号
IPAddress ipAddress = IPAddress.Parse("192.168.1.1");
int port = 8080;
IPEndPoint endPoint = new IPEndPoint(ipAddress, port);
▶ 使用整数和端口
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

// 示例:创建 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 方法
// 成功解析
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 方法(推荐)

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

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 提供了一些常用的属性,用于获取和设置端点的信息。

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

使用示例:

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,用于低级网络操作:

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 通信中常用的类,用于绑定本地端点或连接远程端点。

▶ 绑定本地端点
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

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

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

2. 用于 TcpListener

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

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 可以用来发送和接收数据。

▶ 发送数据
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);
▶ 接收数据
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 类进行网络通信。

▶ 服务器端
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("连接已关闭。");
    }
}
▶ 客户端
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 地址。

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

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

2. 端口超出范围

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

端口合法性验证

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

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

3. 动态获取本地 IP 地址

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

4. 异常处理策略

常见异常类型

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

处理建议

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 双栈支持

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

2)端点池缓存优化

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个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鲤籽鲲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值