文章目录
1. 网络编程
1.1 概念
-
什么是网络编程:
网络编程可以让程序与网络上的其他设备中的程序进行数据交互。现在一般称之为TCP/IP编程,也叫Socket编程,套接字编程,套接字指的是两台设备直接通讯的端点
-
通信模式:
通信模式是指服务器与浏览器或者客户端等通信的方式,可以实现资源共享与信息传递
常见的通信模式有如下2种形式:Client-Server(CS) 、 Browser/Server(BS)
-
俩个Java程序可以通过一个双向的网络通信连接实现数据交换,这个双向线路的一端称为一个Socket
Socket通常用来实现client-server连接
java.net包下定义的俩个类Socket和ServerSocket分别用来实现双向连接的client和server端
建立连接时所需的寻址信息为远程计算机的IP地址和端口号
而UDP协议是不建立连接的
1.2 计算机网络分类
计算机网络按其覆盖的地理范围可分为如下3类:
- 局域网(LAN):局域网是一种在小区域内使用的,由多台计算机组成的网络,覆盖范围通常局限在10 千米范围之内,属于一个单位或部门组建的小范围网
- 城域网(MAN):城域网是作用范围在广域网与局域网之间的网络,其网络覆盖范围通常可以延伸到整个城市,借助通信光纤将多个局域网联通公用城市网络形成大型网络,使得不仅局域网内的资源可以共享,局域网之间的资源也可以共享
- 广域网(WAN) :广域网是一种远程网,涉及长距离的通信,覆盖范围可以是一个国家或多个国家,甚至整个世界。由于广域网地理上的距离可以超过几千千米,所以信息衰减非常严重,这种网络一般要租用专线,通过接口信息处理协议和线路连接起来,构成网状结构,解决寻径问题
1.3 网络通信三要素
-
IP地址:电子设备(计算机)在网络中的唯一标识
-
域名:ip地址是数字型的,为了方便记忆,才有了域名,通过域名地址就能找到ip地址
-
Internet域名是Internet网络上的一个服务器或一个网络系统的名字,在全世界,没有重复的域名。域名的形式是以若干个英文字母和数字组成,由“.”分隔成几部分
-
ip地址和域名是一对多的关系,一个ip地址可以有多个域名,但是相反,一个域名只能有一个ip地址
域名示例:https://www.baidu.com/
-
主机名:主机在局域网中的标识
-
域名的范围要比主机名大,一个域名下可以有多个主机名,域名下还可以有子域名
例如,域名aaaa.com下,有主机server1和server2,其主机全名就是server1.aaa.com和server2.aaa.com
-
-
端口号:应用程序在计算机中的唯一标识。端口使用16位(2个字节)二进制表示,范围是 0~65536
如:MySQL:3306
Tomcat:8080
HTTP:80
-
传输协议:规定了数据传输的规则
基础协议:
- tcp:安全协议,三次握手四次挥手。 速度稍慢
- udp:不安全协议。 速度快
打个比方:IP地址就像酒店名,端口号就像酒店房间号,协议就像酒店规则,例如价格
只要是发数据的就需要确定对方IP地址与端口号,而接数据只需要绑定端口号即可
1.4 套接字与套接字API
-
套接字:是传输层通信端点抽象,仅仅是一个名词
套接字API:网络编程接口(函数集合)套接字位于传输层及应用层之间,是一个应用编程接口,应用程序通过调用此接口进行传输接收数据
-
套接字与套接字API的关系:API创建了套接字,并完成了套接字的功能
-
套接字功能:
传输层真正连接的是套接字,通过套接字将数据发送给特定的进程
传输层如何标识套接字:
会通过ip地址+端口号标识套接字,套接字绑定了主机端口号注意:一台主机上一个端口号只能对应一个进程,一个进程可以监控多个端口
所以网上给的定义:套接字=ip地址+端口号
ip地址及端口号会封装到传输层的数据(报文)中
1.5 IP地址
-
IP(Internet Protocol):全称”互联网协议地址”,是分配给上网设备的唯一标志。
-
常见的IP分类为:IPv4和IPv6
-
其中IPv4使用32位(4字节)的方式为IP地址编号,装换为十进制使用点分十进制表示法
示例:11000000 10101000 00000001 01000010 ==> 192.168.1.66
-
而IPv6使用128位(16个字节)的方式为IP地址编号,号称可以为地球每一粒沙子编号
IPv6使用冒分十六进制表示法:IPv6分成8个整数(每俩个字节一个数),每个整数用四个十六进制位表示, 数之间用冒号(:)分开
示例:
-
在我们的主机上通常使用域名访问服务器,然后服务器通过ip地址定位到我们的主机,给我们返回信息
-
IPv4IP地址分类:可以分为公网地址、和私有地址(局域网使用)
其中192.168. 开头的就是常见的局域网地址,范围即为192.168.0.0–192.168.255.255,专门为组织机构内部使用
-
特殊IP地址:
本机IP: 127.0.0.1或者localhost(域名):称为回送地址也可称本地回环地址,只会寻找当前所在本机
-
IP常用命令:
ipconfig:查看本机IP地址
ping IP地址:检查网络是否连通,也可以ping域名
1.5.1 IP地址操作类:InetAddress
- InetAddress翻译:网络地址,此类表示Internet协议(IP)地址,通过这个类可以创建IP地址对象,属于java.net包下
- InetAddress类无构造器,他的对象一般通过这个类的静态方法获取该类对象
- 常用API:
方法名 | 说明 |
---|---|
public static InetAddress getLocalHost() | 返回本主机的地址对象 |
public static InetAddress getByName(String host) | 得到指定主机的IP地址对象,参数是域名或者IP地址 |
public String getHostName() | 获取此IP地址的主机名 |
public String getHostAddress() | 返回IP地址字符串 |
public boolean isReachable(int timeout) | 在指定毫秒内连通该IP地址对应的主机,连通返回true |
代码示例:
// 获取本机地址对象
InetAddress ip = InetAddress.getLocalHost();
// 获取主机名
System.out.println(ip.getHostName());
// 获取IP地址
System.out.println(ip.getHostAddress());
// 通过域名获取ip地址
InetAddress ip2 = InetAddress.getByName("www.baidu.com");
// 获取主机名
System.out.println(ip2.getHostName());
// 获取IP地址
System.out.println(ip2.getHostAddress());
// 判断五秒内能不能联通百度,类似ping ip地址
System.out.println(ip2.isReachable(5000));
1.6 端口
- 端口号:标识正在计算机设备上运行的进程(程序),被规定为一个 16 位的二进制,范围是 0~65535,因此一台机器最多有65536个端口,一个应用程序可以占用多个端口号,如果一个端口号被一个应用程序占用,那其他应用程序就不能使用这个端口了
- 仅使用IP地址只能标识一台计算机,想要准确标识到这台计算机上的某个软件,需要通过IP地址加端口号
- 端口号是一个虚拟的概念,是一个逻辑接口
- 端口号本身分为TCP端口和UDP端口,TCP端口和UDP端口都有65536个,并且是不同的,例如TCP的8888端口和UDP的8888端口是俩个不同的端口
- 周知端口:0~1023,被预先定义的知名应用占用(如:HTTP占用 80,HTTPS占用443, FTP占用21)
注册端口:1024~49151,分配给用户进程或某些应用程序。(如:Tomcat占 用8080,MySQL占用3306, Oracle占用1521)
动态端口/私有端口:49152到65535,之所以称为动态端口,是因为它 一般不固定分配某种进程,而是动态分配 - 端口常用命令:
netstat -ano : 查看所有端口
netstat -ano|findstr "端口号" : 查看指定端口
tasklist|findstr "端口号" : 查看指定端口的进程
netstat -ano|findstr "端口号" : 查看指定端口
tasklist|findstr "端口号" : 查看指定端口的进程
-
注意:
我们自己开发的程序选择注册端口,且一个设备中不能出现两个程序的端口号一样,否则出错,并且我们一般选择占用1024以上的端口号,因为1024以下的端口号随时有可能被系统占用
但不同设备里的某个程序端口号要一致
1.6.1 InetSocketAddress类
-
InetSocketAddress也属于java.net包下,这个类实现了 IP 套接字地址(即IP 地址 + 端口号)
-
构造器:
构造器 | 说明 |
---|---|
InetSocketAddress(InetAddress addr, int port) | 根据 IP 地址和端口号创建套接字地址 |
InetSocketAddress(int port) | 创建套接字地址,其中 IP 地址为通配符地址,端口号为指定值 |
InetSocketAddress(String hostname, int port) | 根据主机名和端口号创建套接字地址 |
- 常用方法
方法名称 | 说明 |
---|---|
InetAddress getAddress() | 获取 InetAddress,即IP地址对象 |
String getHostName() | 获取 hostname主机名 |
int getPort() | 获取端口号 |
1.7 协议
- 概念:连接和通信数据的规则被称为网络通信协议
- 网络通信协议有两套参考模型,分别是OSI参考模型和TCP/IP参考模型:
- OSI参考模型:世界互联协议标准,全球通信规范,由于此模型过于理想化,未能在因特网上进行广泛推广
- TCP/IP参考模型(或TCP/IP协议):事实上的国际标准
1.7.1 通信协议的分层思想
在参考模型中涉及到了通信协议的分层思想
那为什么在通信协议中要分层呢:
在通信中,每个节点之间的联系是很复杂的
因此我们在制定协议时需要先将这些复杂的成分进行拆分,变成简单的成分后再加他们联系起来(即分层再联系)
在拆分到复合的过程中,最常用的方式就是层次方式
采用这种方式之后,同层间可以互相通信,同时上一层可以调用下一层,但是和再下一层就没有关系了
这样子各层之间不会相互影响,降低了耦合度,利于系统的开发与维护,同时也做到了将复杂成分拆分再复合产生联系
分层规定/方法:
将应用程序作为最高层,将物理通信线路作为最底层,对其间的通信协议处理分为若干层
同时规定每一层的任务与接口标准
1.7.2 对于TCP/IP协议中的四层分析
TCP/IP协议中的四层分别是应用层、传输层、网络层和链路层,每层分别负责不同的通信功能。
- 应用层:主要负责应用程序的协议,例如HTTP协议、FTP协议等
- 传输层:主要使网络程序进行通信,在进行网络通信时,可以采用TCP协议,也可以采用UDP协议
- 网络层:网络层是整个TCP/IP协议的核心,它主要用于将传输的数据进行分组,将分组数据发送到目标计算机或者网络
- 数据链路层:链路层是用于定义物理传输通道,通常是对某些网络连接设备的驱动协议,例如针对光纤、网线提供的驱动
而我们编写的程序位于应用层,因此我们的程序是和TCP/UDP打交道的。
1.7.3 TCP协议
TCP(Transmission Control Protocol) :传输控制协议
TCP协议特点:
- 使用TCP协议,必须双方先建立连接,它是一种面向连接的可靠通信协议
- 传输前,采用“三次握手”方式建立连接,所以是可靠的
- TCP协议就像打电话,需要先接通,等对方回应了才会跟对方说话
- 在连接中可进行大数据量的传输
- 连接、发送数据都需要确认,且传输完毕后,还需释放已建立的连接,通信效率较低
使用TCP协议通信场景:
- 对信息安全要求较高的场景,例如:文件下载、金融等数据通信
三次握手:
其实服务器端的响应就相当于告诉客户端:我收信息和发信息都没毛病
客户端的第三次握手就相当于告诉服务器:俺发信息也没毛病
所以三次握手的主要作用就是确认双方的接收能力和发送能力是否正常,同时指定自己的初始化序列号(发送连接请求时会将自己的序列号也发过去)为后面的可靠性传送做准备
其中第三次握手可以携带数据,第一次第二次不能携带数据
第一次握手不携带数据是因为携带数据会让服务器更容易受到攻击
四次挥手:
为什么挥手比握手多一次:
其实当客户端发出取消连接请求时仅仅表示客户端不再发送数据了,但是还能接受数据
接着服务器端收到请求先返回一个响应,表示自己收到请求了,而此时服务器端可能还有需要处理和发送的数据
等服务器端把最后的数据处理完毕之后,才会向客户端发出确认取消信息
因此比握手多了一次
1.7.4 UDP协议
- UDP(User Datagram Protocol):用户数据报协议
- 数据报:网络传输的基本单位
- UDP是一种无连接、不可靠传输的协议
- 将数据源IP、目的地IP和端口封装成数据包,不需要建立连接 ,也不会确认对方是否存在,是否准备好,直接就给丢了过去,接收方收到也不确认,故是不可靠的
- UDP就好比发电报,发出去就完事了,对方收没收到可不关他事
- 每个数据包的大小限制在64KB内
- 可以广播发送 ,发送数据结束时无需释放资源,开销小,速度快,通信效率高
UDP协议通信场景:
- 语音通话,视频会话等,可以减小延迟,并且就算损失了几包数据可能也只是画面模糊一点而已
打个比方,UDP协议就像小视频里隔着马路把菜扔过去
其中需要人(DatagramSocket发送端接收端对象)来扔菜(数据),同时还需要一个菜盘子(DatagramPacket数据包对象)装菜
2. java.net包
在java中,用于网络编程的类与API都放在了java.net包下
下面是实现TCP与UDP协议的类中较常用的类示意图:
其中:
-
InetAddress: 此类表示Internet协议(IP)地址,IP是低级协议
-
SocketAddress : 套接字对象
此类表示没有协议附件的套接字地址。 作为一个抽象类,它意味着要使用特定的,依赖于协议的实现进行子类化。
它提供了一个由套接字用于绑定,连接或作为返回值的不可变对象子类:InetSocketAddress: 此类实现IP套接字地址(IP地址+端口号)
它也可以是一对(主机名+端口号)它提供了一个由套接字用于绑定,连接或作为返回值的不可变对象
-
DatagramPacket: UDP协议通信中的数据报包对象,用于封装数据, 而TCP协议中通过IO流传输数据
提供了获取数据长度,获取数据包中数据,获取InetAddress与SocketAddress的API
子类:MulticastSocket :
该类在父类基础上,增加了用于加入因特网上的其他组播主机的“组”的附加功能
-
DatagramSocket: UDP协议中的发送端和接收端对象, 用于发送和接收数据报的套接字
提供了发送数据与接受数据的API(返回值都为空)
-
Socket : TCP协议中的客户端套接字对象
提供了获取字节输入流与输出流的API, 直接在字节流中读写数据即可实现客户端与服务器端的交互
-
ServerSocket : TCP协议中的服务器端套接字对象
提供了接收客户端的Socket通信连接的API
-
URL : 表示统一资源定位符,指向万维网上的“资源”的指针。 资源可以是文件或目录这样简单的东西,也可以是对更复杂的对象的引用,例如对数据库或搜索引擎的查询。 有关URL类型及其格式的更多信息
以上java.net包下的类具体使用请看此专栏中的UDP通信编程与TCP通信编程以及URL介绍