1.网络的基本概念
网络开发已经成为每个开发人员的核心技能。很多应用程序使用网络,如即时通讯软件(微信,QQ等),电子邮件,浏览器,远程控制等。
1.1网络
网络 是一系列设备(计算机,打印机,路由器…)的集合,这些设备被称为网络节点。节点之间可以通过电缆,无线电波,光纤交流。
每个网络节点都有唯一标识,被称为 地址(Address) 。
计算机之间来回传输数据需要协议(protocol),以保证计算机能够找到另一台计算机,并且保证它们之间能够互相理解。
1.2 网络分层
ISO制定的OSI参考模型的过于庞大、复杂招致了许多批评。与此对照,由技术人员自己开发的 TCP/IP协议栈 获得了更为广泛的应用。
TCP/IP参考模型分为四个层次:应用层、传输层、网络互连层和主机到网络层。
主机到网络层:
实际上TCP/IP参考模型没有真正描述这一层的实现,只是要求能够提供给其上层-网络互连层一个访问接口,以便在其上传递IP分组。由于这一层次未被定义,所以其具体的实现方法将随着网络类型的不同而不同。
网络互连层:
网络互连层是整个TCP/IP协议栈的核心。它的功能是把分组发往目标网络或主机。同时,为了尽快地发送分组,可能需要沿不同的路径同时进行分组传递。因此,分组到达的顺序和发送的顺序可能不同,这就需要上层必须对分组进行排序。网络互连层定义了分组格式和协议,即IP协议(Internet Protocol)。
传输层:
在TCP/IP模型中,传输层的功能是使源端主机和目标端主机上的对等实体可以进行会话。在传输层主要定义了两种服务质量不同的协议。即:传输控制协议TCP(transmission control protocol)和用户数据报协议UDP(user datagram protocol)。
【TCP协议】是一个面向连接的、可靠的协议。它将一台主机发出的字节流无差错地发往互联网上的其他主机。在发送端,它负责把上层传送下来的字节流分成报文段并传递给下层。在接收端,它负责把收到的报文进行重组后递交给上层。TCP协议还要处理端到端的流量控制,以避免缓慢接收的接收方没有足够的缓冲区接收发送方发送的大量数据。
【UDP协议】是一个不可靠的、无连接协议,主要适用于不需要对报文进行排序和流量控制的场合。
应用层:
应用层面向不同的网络应用引入了不同的应用层协议。其中,有基于TCP协议的,如文件传输协议(FTP)、虚拟终端协议(TELNET)、超文本链接协议(HTTP),也有基于UDP协议的。
1.3 IP地址,域名与端口
IP地址:
用二进制来表示,每个IP地址长32bit,比特换算成字节,就是4个字节。例如一个采用二进制形式的IP地址是一串很长的数字,人们处理起来也太费劲了。为了方便人们的使用,IP地址经常被写成十进制的形式,中间使用符号“.”分开不同的字节。于是,上面的IP地址可以表示为“10.0.0.1”。IP地址的这种表示法叫做“点分十进制表示法”,这显然比1和0容易记忆得多。
域名:
IP地址是Internet主机的作为路由寻址用的数字型标识,人不容易记忆。因而产生了域名(domain name)这一种字符型标识。当访问一个域名时,DNS服务器会把域名转化为相应的IP地址再进行访问
端口:
在Internet上,各主机间通过TCP/IP协议发送和接收数据包,各个数据包根据其目的主机的ip地址来进行互联网络中的路由选择,把数据包顺利的传送到目的主机。大多数操作系统都支持多程序(进程)同时运行,那么目的主机应该把接收到的数据包传送给众多同时运行的进程中的哪一个呢?显然这个问题有待解决,端口机制便由此被引入进来。
如果把IP地址比作一间房子 ,端口就是出入这间房子的门。真正的房子只有几个门,但是一个IP地址的端口可以有65536(即:2^16)个之多!端口是通过端口号来标记的,端口号只有整数,范围是从0 到65535(2^16-1)。
2.Java中的网络编程基础
2.1 java.net.InetAddress类
InetAddress是Java对IP地址的封装,在java.net中有许多类都使用到了InetAddress,包括ServerSocket,Socket,DatagramSocket等等。
InetAddress对域名进行解析是使用本地机器配置或者网络命名服务,如域名系统(DNS)等实现。对于DNS来说,本地需要向DNS服务器发送查询的请求,然后服务器根据一系列的操作,返回对应的IP地址,为了提高效率,通常本地会缓存一些主机名与IP地址的映射,这样访问相同的地址,就不需要重复发送DNS请求了。在java.net.InetAddress类同样采用了这种策略。在默认情况下,会缓存一段有限时间的映射,对于主机名解析不成功的结果,会缓存非常短的时间(10秒)来提高性能。
对象的建立
InetAddress的构造函数是私有的,所以需要通过它提供的静态方法来获取,主要有以下的方法:
static InetAddress[] getAllByName(String host)
static InetAddress getByAddress(byte[] addr)
static InetAddress getByAddress(String host,byte[] addr)
static InetAddress getByName(String host)
static InetAddress getLocalHost()
//getByName(String host)方法。InetAddress会尝试做连接DNS服务器,并且获取IP地址的操作。
InetAddress address = InetAddress.getByName("wwww.baidu.com");
//getAllByName()方法是根据主机名返回其可能的所有InetAddress对象,保存在一个数组中。
InetAddress[] addressArray=InetAddress.getAllByName("wwww.taobao.com");
//getLocalHost(),返回的是本地地址
InetAddress address_local=InetAddress.getLocalHost();
上面代码使用 System.out.println()
输出,结果如下
wwww.baidu.com/111.13.101.208
[wwww.taobao.com/140.205.230.49]
Jiazhi-PC/192.168.0.101
对象方法
InetAddress address=InetAddress.getByName("www.baidu.com");
//getAddress()方法获取地址数组
System.out.println(Arrays.toString(address.getAddress()));
//获取主机ip地址
System.out.println(address.getHostAddress());
//获取域名
System.out.println(address.getHostName());
输出如下:
[-76, 97, 33, 108]
180.97.33.108
www.baidu.com
注意:getAddress()这个方法返回的byte数组是有符号的。在Java中byte类型的取值范围是-128?127。如果返回的IP地址的某个字节是大于127的整数,在byte数组中就是负数。需要加256即可,在上面中-76+256=180正好。
2.2 java.net.NetworkInterface类
NetworkInterface定义了很多获取网络接口信息的方法,其中很多是jdk1.6版本以后才加入进去的。主要有以下方法:
String displayName() 获取网络接口的显示名称
byte[] getHardwareAddress() 获取网络接口的物理地址,通常是MAC地址
int getMTU()返回此接口的最大传输单元(Maximum Transmission Unit,MTU)
String getName()获取此网络接口的名称
boolean isLoopback()返回网络接口是否是回送接口
boolean isPointToPoint()返回网络接口是否是点对点接口
boolean isUp()返回网络接口是否已经开启并运行
boolean isVirtual()返回此接口是否是虚拟接口(也称为子接口)。
实例:
// 获取本机所有网卡信息
Enumeration<NetworkInterface> enums = NetworkInterface.getNetworkInterfaces();
while (enums.hasMoreElements()) {
System.out.println(enums.nextElement());
}