目录
网络是什么?
将不同区域的电脑连接到一起,组成局域网、 城域网或广域网。把分布在不同地理区域的计算机与专门的外部设备用通信线路互连成-一个规模大、功能强的网络系统,从而使众多的计算机可以方便地互相传递信息,共享硬件、软件、数据信息等资源。
通讯协议
计算机网络中实现通信必须有一些约定。即通信协议。对速率、传输代码、代码结构、传输控制步骤、出错控制等制定标准。
通信接口
为了使两个结点之间能进行对话,必须在它们之间建立通信工具(即接口),使彼此之间能进行信息交换。接口包括两部分。
- 硬件装置:实现结点之间的信息传送。
- 软件装置:规定双方进行通信的约定协议。
网络分层
由于结点之间联系很复杂,在制定协议时,把复杂成份分解成一些简单的成份,再将它们复合起来。最常用的复合方式是层次方式,即同层间可以通信、上一层可以调用下一层,而与再下一层不发生关系。
这里又分为理想的OSI七层模型,与实际使用TCP/IP模型。我们的WEB应用属于应用层,而JAVA网络编程则属于传输层
OSI七层模型 | TCP/IP模型 | 协议 |
应用层 | 应用层 | Telnet,FTP,HTTP,DNS,SMTP等 |
表示层 | ||
会话层 | ||
传输层 | 传输层 | TCP,UDP |
网络层 | 网络层 | IP,ARP,RARP,ICMP |
数据链路层 | 网络接口层 | 各种通信网络接口(以太网等) (物理网络) |
物理层 |
数据封装
Data Encapsulation是指将协议数据单元(PDU)封装在一组协议头和协议尾中的过程。在OSI七层参考模型中,每层主要负责与其它机器上的对等层进行通信。该过程是在协议数据单元(PDU)中实现的,其中每层的PDU一般由本层的协议头、协议尾和数据封装构成。
- 应用层:准备数据
- 传输层:接收应用层的数据,并添加上TCP控制信息,封装完成后的数据单元称为段(Segment),并将段交给网络层
- 网络层:接收传输层的段,并添加IP头部,封装完成后的数据单元称为包(Packet),并将包交给数据链路层
- 数据链路层:接收网络层的包,添加MAC头部和尾部,封装完成后的数据单元称为帧(Frame),并将帧交给物理层
- 物理层:接收数据链路层的帧,转成比特流,在网线中传递
发送数据处理的方式是从高层到底层,逐层进行数据封装
数据拆封是和数据封装相反的过程
IP地址(InetAddress)
IP地址是用来标识网络中一个通信实体的地址。(类比为快递中,你写的小区地址)。
IP地址分类
- IPV4: 32位地址,以点分十进制表示,如192. 168. 0. 1
- IPV6: 128位(16个字节)写成8个16位的无符号整数,每个整数用四个十六进制位表示,数之间用冒号(: )分开,如: 3ffe:3201: 1401: 1280:c8ff:fe4d: db39: 1984
特殊的IP
- 127.0.0.1——本机地址
- 192. 168. 0. 0~192.168. 255 255——私有地址,属于非注册地址,专门为组织机构内部使用
InetAddress
Java使用InetAddress封装了IP地址
// 根据输入的域名获取IP
InetAddress inetAddress = InetAddress.getByName("www.baidu.com");
System.out.println(inetAddress.getHostAddress()); // 获取IP地址
System.out.println(inetAddress.getHostName()); // 获取主机名
// 获取本机的IP
InetAddress inetAddress2 = InetAddress.getLocalHost();
System.out.println(inetAddress2.getHostAddress());
System.out.println(inetAddress2.getHostName());
Socket端口(InetSocketAddress)
IP地址用来标识一台电脑,但电脑中又有很多软件,如何找到对应的软件呢,就要用到端口。(类比为小区中的门牌号)
同一协议端口不能冲突,不同协议最好不要冲突。
端口分类
- 公认端口:0~1023——比如80端口分配给www,21端口分配给FTP
- 注册端口:1024~49151——分配给用户进程或应用程序
- 动态/私有端口:49152~65535
我们使用端口时最好越大越好,越不容易冲突。
InetSocketAddress
Java使用InetSocketAddress封装了IP+端口号或主机名+端口号
// 通过主机名+端口号创建
InetSocketAddress socketAddress = new InetSocketAddress("www.baidu.com", 80);
System.out.println(socketAddress.getAddress()); // 获取主机名和IP的对应关系
System.out.println(socketAddress.getPort()); // 获取端口
URL统一资源定位器(URL)
类比为具体的收件人姓名
URI、URL、URN
- URI:统一资源标志符,用于抽象标识或抽象物理资源的紧凑字符串,它有两种表现形式(URL、URN)
- URL:统一资源定位器,一种定位资源且具有访问机制的字符串,比URI更为强大,前者只能定位,一个标准(非必须)的URL需要包括协议,域名|IP,端口,资源,参数,锚点
- URN:统一资源名称,通过特定命名空间中的唯一名称或ID来标识资源(磁力链接)
URL
Java使用URL类封装了URL
// 不会验证url是否存在
URL url = new URL("https://www.baidu.com:80/index.html?a=1&b=2#hello");
System.out.println("协议:" + url.getProtocol());
System.out.println("域名|ip:" + url.getHost());
System.out.println("端口:" + url.getPort());
System.out.println("资源(file):" + url.getFile());
System.out.println("资源(path):" + url.getPath());
System.out.println("参数:" + url.getQuery());
System.out.println("锚点:" + url.getRef());
使用Java实现简单爬虫
// 获取URL
URL url = new URL("https://www.jd.com");
// 下载资源
InputStream is = url.openStream(); // 打开字节输入流,将网络资源输入
// 将字节流转换为字符流
BufferedReader br = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
// 上面也可以直接传递"UTF-8",看源码能看到内部也是将传递的字符串拿给了Charset
// 读取,进行分析等操作
String msg = "";
while ((msg = br.readLine()) != null) {
System.out.println(msg);
}
br.close();
当然不是所有的网站都能通过上面的方式爬到资源的,有些网站会拒绝Java的直接访问。比如
这个时候该怎么解决呢?我们发现我们直接通过浏览器也是能够访问的,所以我们就自然的想到,Java是否能模拟浏览器访问?要模仿浏览器的访问,我们可以看到请求头里一个关键的属性叫做,UA(User-Agent),也就是用户代理,它能够让服务器识别客户的操作系统,浏览器类型等信息。UA属性的值可以在浏览器控制台请求头里找到。
// 获取URL,不允许直接读取的
URL url = new URL("http://www.dianping.com");
// 下载资源, 以浏览器访问的方式去读取连接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// 设置访问方法
connection.setRequestMethod("GET");
// 设置UA
connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3314.0 Safari/537.36 SE 2.X MetaSr 1.0");
InputStream is = connection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
String msg = "";
while ((msg = br.readLine()) != null) {
System.out.println(msg);
}
br.close();