“.NET 4.0 网络开发入门之旅系列文章”——
IP 知多少?(下)
前一部分: IP 知多少?(中)
4.
IP
终结点
现在介绍
.NET
网络开发中最重要的一个概念——
IP
终结点,
.NET
基类库中使用
IPEndPoint
类型代表它。
要想理解它,还得从
TCP/IP
说起。
前面说过,所有连在网络上的计算机都必须要有一个唯一的
IP
地址,它用于区分开网络上的不同计算机,现在的问题是:一台网络计算机上可能跑着多个
网络应用程序,它们可能会使用同一个网络接口从网络中接收(或发送)数据,因而共享同一个
IP
地址,在这种情况下,你怎么将到达主机的数据包转发给真正的“需求者”?
为了解决这个问题,
TCP/IP
协议设计者引入了“端口(
Port
)”这个概念,规定每个提供网络服务的应用程序都必须指定一个“端口”,不同的网络应用程序不能使用相同的端口。
请看以下
TCP
数据包的结构:
图
4
每个
TCP
数据包都包容着两个端口信息(每个端口占
2
个字节,是一个
16
位的二进制数值,所以,最大端口值为
2
的
16
次方减
1
,为
65535
)。
Source port
指明发送此数据包的网络应用程序使用的端口,
Destination port
指明接收方网络应用程序使用的端口。
这样一来,接收方计算机依据
Destination
port
,就可以把此数据包转发给真正的网络应用程序。
在
Windows
平台上,操作系统内核中的
TCP/IP
驱动(
\Windows\System32\drivers
文件夹下的
tcpip.sys
)负责完成处理
TCP
数据包的工作。
端口的问题解决了,但我们在
TCP
数据包中没有看到
IP
地址啊?没有这个地址,数据包怎样知道应该被送给哪台计算机?
方法是这样的。
由于
TCP
协议建构于
IP
协议之上,
TCP
数据包由
IP
数据包承载,(图
5
)。
图
5
图
5
中清晰地展示出
IP
数据包中包容有发送此数据包的主机
IP
地址(即
Source IP Address
)和接收此数据包的主机
IP
地址(即
Destination IP Address
)信息。
图
5
中的“数据(
Data
)”部分,包容的就是
TCP
数据包。
由此可知,
IP
地址与端口唯一地标识了一个网络中的网络应用程序,我们将这个组合称为“
IP
终结点(
IP EndPoint
)”,
IP EndPoint
是一个网络服务的访问点。
提示:
类似地,
WCF
中也有一个服务终结点(
ServiceEndpoint
),它代表一个
WCF
服务的访问点。大家看到了软件技术各领域之间的联系了吗?
在
.NET
中,使用
IPEndPoint
类表示一个
IP
终结点(图
6
),它派生自抽象基类
EndPoint
,注意它的
3
个属性(
Address\AddressFamily\Port
)所表达的重要信息。
图
6
在
.NET
网络应用程序中,套接字(
Socket
)对象必须绑定到一个
IPEndPoint
对象。
为了方便,我们编写了一个静态方法
GetRemoteMachineIPEndPoint
,并将其添加到前面介绍过的
AddressHelper
静态类中:
///
以交互方式生成有效的远程主机访问终结点
,
适用于控制台程序
public static IPEndPoint GetRemoteMachineIPEndPoint()
{
IPEndPoint iep = null;
try
{
Console.Write("
请输入远程主机的
IP
地址:
");
IPAddress address = IPAddress.Parse(Console.ReadLine());
Console.Write("
请输入远程主机打开的端口号:
");
int port =
Convert.ToInt32(Console.ReadLine());
if (port > 65535 || port
< 1024)
throw new Exception("
端口号应该为
[1024,65535]
范围内的整数
");
iep = new IPEndPoint(address,
port);
}
catch (ArgumentNullException)
{
Console.WriteLine("
输入的数据有误!
");
}
catch (FormatException)
{
Console.WriteLine("
输入的数据有误!
");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return iep;
}
后面的示例将大量使用此方法创建可供
Socket
绑定的
IP
终结点对象。
1.
我可以使用哪个端口?
在实际开发中,经常需要为某个网络服务动态地指定一个端口,为避免与一些重要的网络服务程序冲突(比如
80
端口固定为
Web
服务器所使用)通常要求这个端口应位于
[1024,65535]
这区间内。
现在的问题是怎样从中选取一个没有被占用的端口?要知道,某台计算机上运行的网络应用程序可能有多个,而且在不同的时间段内也不一样。
IPAddress.Any
这个特殊的地址可以派上用场了,当一个套接字对象绑定一个
IPAddress.Any
对象时,
Windows
会自动为其分配一个未被占用的端口号,当套接字对象不再使用而可以被回收时,此端口将可以被复用。
由此我们可以得到以下的思路:
创建一个套接字对象,让它绑定到
IPAddress.Any
对象,提取出系统分配的端口,然后再销毁掉此套接字对象。
Socket
对象实现了
IDisposable
接口,所以可以使用
using
关键字来自动回收其占用的资源:
以下是我们编写的代码片段:
public static int
GetOneAvailablePortInLocalhost()
{
IPEndPoint
ep = new IPEndPoint(IPAddress.Any, 0);
using
(Socket tempSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp))
{
tempSocket.Bind(ep);
IPEndPoint
ipep = tempSocket.LocalEndPoint as IPEndPoint;
return
ipep.Port;
}
}
提示:
一个对象实现
IDisposable
接口有许多讲究,
.NET
为此设计了一个“
IDisposable
编程模式”,请参看《
.NET 4.0
面向对象编程漫谈》的
5.5
节《与对象销毁相关的话题》
呵呵,现在,我们在应用程序中可以随时调用
AddressHelper. GetOneAvailablePortInLocalhost()
方法获取一个可用端口了,真给力!
但别高兴得太早!
你考虑过两个网络应用程序(或同一应用程序的两个线程)同时调用上述方法获取可用端口的情形吗?
这时,无法保证此方法的两次调用一定返回不同的端口。如果两个
Socket
对象尝试绑定到同一个
IPEndPoint
,将会引发一个
SocketException
异步。
为此,我们需要一个能跨越进程边界的线程同步手段。
命名的互斥同步对象
Mutex
可以解决这个问题,修正后的代码如下:
//
获取本机当前可用的端口号,此方法是线程安全的
public static int
GetOneAvailablePortInLocalhost()
{
Mutex mtx = new Mutex(false,
"MyNetworkLibrary.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
ipep = tempSocket.LocalEndPoint as IPEndPoint;
return
ipep.Port;
}
}
finally
{
mtx.ReleaseMutex();
}
}
提示:
《
.NET 4.0
面向对象编程漫谈
》的
17.3.2
节详细介绍了
Mutex
对象的使用方法,
15.3.5
节介绍了如何活用命名
Mutex
对象实现应用程序的“单例模式”(即此应用程序不允许同时启动两个进程),以及如何利用它来现进程间的“通知机制”。
建议读者对照学习。
好了,本文就写到这里吧。
给读者留个作业:
1
依据本文介绍的内容使用
Visual Studio
创建类库项目
MyNetworkLibrary
,将
GetLocalhostIPv4Addresses()
、
GetRemoteMachineIPEndPoint()
、
GetOneAvailablePortInLocalhost
()
三个方法封装到
AddressHelper
静态类中,后面文章的示例将调用它们。
2
.NET
基类库中提供了一个
Ping
组件用于检测网络连接性,请先通过
MSDN
自学它的使用方法。
========================================================
点击查看本系列的下一篇文章
分享到:
相关推荐
ASP.NET 4.0 网站开发与项目实战 光盘 包括PPT和Sample,不包括视频教程
精通C#与.NET 4.0数据库开发源码 --------------------------------------------- 这是随书配套源码,共 11.3M. --------------------------------------------- 按我名字搜索,也有本书的PDF档下载和其它的C#与...
找了很久的资源,亲测可在.net4.0 环境下使用。。。。。。
.NET4.0离线安装包
ASP.NET 4.0从入门到精通(视频实战版).pdf
ASP.net4.0从入门到精通 张昌龙 辛永平
ASP.NET 4.0网站开发入门教程
靳华、洪石丹编著的《ASP.NET 4.0编程技术大全(附光盘)》全方位讲解了C#语言基础、ASP.NET开发、ASP.NET 4.0整合WF+WCF等ASP.NET开发技术的方方面面。本书通过理论知识的详细讲解和实际开发项目的实践学习,帮助...
FastReport.Net4.0_Full 安装程序,解决了PDF打印时,取消了“适合页面大小”的默认设置,使报表设计大小与打印完全一致。
Newtonsoft.Json.Net 4.0下载.rar
ASP.NET 4.0从入门到精通书后代码
Asp.Net 4.0从入门到精通书本 (源代码).
本技术资源包括了我在博客上发表的“.NET 4.0并行计算技术基础”系列文章中的所有示例源码,并包含一个PDF,汇总了所有文章。 与作者互动请访问http://blog.csdn.net/bitfan/archive/2009/10/26/4728180.aspx 更多...
ASP.NET 4.0从入门到精通_pdf第七部分 把7个包一起解压缩即可
ASP.NET4.0网站开发与项目实战 ASP.NET+AJAX应用1
精通ASP.NET 4.0
精通C#与.NET 4.0数据库开发 1 OF 2 --------------------------------------------- PDF文档,共有 2 个分卷文件,请全部下载完才能顺利解压缩 --------------------------------------------- 后续也可按我...
精通C#与.NET 4.0数据库开发 2 OF 2 --------------------------------------------- PDF文档,共有 2 个分卷文件,请全部下载完才能顺利解压缩 --------------------------------------------- 后续也可按我...
《ASP.NET4.0从入门到精通》随书教学视频
随着计算机的广泛应用和软件技术的发展,不同的操作系统、开发平台、运行框架、开发技术的不兼容性日益突出,给开发...微软借助.NET框架将Windows下各种应用程序开发有机集成起来,为开发人员提供统一的开发接口和类库