网络编程
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Threading;
using System.Net.Sockets;
namespace ConsoleApplication1
{
public class AddressHelper
{
/// <summary>
/// 获取主机IPv4
/// </summary>
/// <returns></returns>
public IPAddress[] GetLocalhostIPv4Address()
{
//获取主机名
string localhostName = Dns.GetHostName();
//通过主机名获取主机地址信息
IPHostEntry host = Dns.GetHostEntry(localhostName);
List<IPAddress> addresses = new List<IPAddress>();
foreach (IPAddress ip in host.AddressList)
{
if (ip.AddressFamily==System.Net.Sockets.AddressFamily.InterNetwork)
{
addresses.Add(ip);
}
}
return addresses.ToArray();
}
/// <summary>
/// 获取一个网络端点表示为IP地址和端口号
/// </summary>
/// <returns></returns>
public IPEndPoint GetRemoteMachineIPEndPoint()
{
IPEndPoint iep = null;
try
{
Console.WriteLine("请输入远程主机的IP:");
IPAddress address = IPAddress.Parse(Console.ReadLine());
Console.WriteLine("请输入远程主机打开的端口号:");
int port = Convert.ToInt32(Console.ReadLine());
if (port > 65535 || port < 1024)
{
throw new Exception("端口号应该在[1024,65535]之间");
}
//ip终结点
iep = new IPEndPoint(address, port);
}
//将空引用传递
catch (ArgumentNullException)
{
Console.WriteLine("输入数据有误!不允许空");
}
//数据格式不正确
catch (FormatException)
{
Console.WriteLine("输入数据有误!格式不正确");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return iep;
}
/*1、我们可以使用哪个端口?
* 在实际开发中,经常为某个网络服务动态指定一个端口,为了避免与某些重要的网络服务程序冲突(比如80端口固定为Web服务器使用的)
* 通常要求这个端口位于[1024,65535]之间
* 我们如何选取一个没有被占用的端口呢?
* IPAddress.Any这个特殊的地址可以派上用场,当一个套接字对象绑定一个IPAddress.Any对象时,windows会为其自动分配一个未被占用的端口号
* 当套接字不在使用时被回收,可以重复使用
* 由此可以得到思路:
* 创建一个套接字对象,让他绑定到IPAddress.Any对象,提取系统分配给的端口,然后再销毁此套接字对象。
* Socket对象实现了IDisposable接口所以使用using关键字来自动回收其占用的资源
* 为了防止2个网络程序(或者2个线程)同时调用可用端口的情况吗?
* 这时,无法保证此方法的两次调用一定返回不同的端口。如果两个 Socket 对象尝试绑定到同一个 IPEndPoint ,将会引发一个 SocketException 异步。
* 为此,我们需要一个能跨越进程边界的线程同步手段。命名的互斥同步对象 Mutex 可以解决这个问题
*/
/// <summary>
/// 获取本机当前可用的端口号,此方法是线程安全的
/// </summary>
/// <returns></returns>
public int GetOneAvailableInLocalhost()
{
Mutex mtx = new Mutex(false, "ConsoleApplication1.AddressHelper.GetOneAvailablePort");
try
{
mtx.WaitOne();
IPEndPoint ep = new IPEndPoint(IPAddress.Any, 0);
using (Socket tempSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
tempSocket.Bind(ep);
IPEndPoint iep = tempSocket.LocalEndPoint as IPEndPoint;
return iep.Port;
}
}
catch (Exception)
{
throw;
}
finally
{
mtx.ReleaseMutex();
}
}
}
}