Lesson27_网络编程
网络编程
软件结构
- C/S结构:全称为Client/Server结构,是指客户端和服务器结构,常见的QQ迅雷等软件
- B/S结构:全称为Browser/Server结构,是指浏览器和服务器结构,常见浏览器有谷歌、火狐等
- 两种架构各有优势,但是无论哪种架构,都离不开网络的支持。
- 网络编程就是在一定的协议下,实现两台计算机的通信的程序。
计算机网络
是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,形成一个规模大、功能强的网络系统。
在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源(硬件、软件、数据信息等)共享和信息传递的计算机系统
设备之间在网络中进行数据的传输,发送/接收数据。
网络编程概念
在网络通信协议下,实现网络互连的不同计算机上运行的程序间可以进行数据交换
OSI网络七层模型
- 物理层:在物理层上所传数据的单位是比特。物理层的任务就是透明地传送比特流。
- 数据链路层:互联设备之间传送和识别数据帧。我们知道,两个主机之间的数据传输,总是在一段一段的链路上传送的,也就是说,在两个相邻结点之间传送数据是直接传送的(点对点),这时就需要使用专门的链路层的协议。
- 网络层:为数据包选择路由。
- 传输层:起着可靠传输的作用。只在通信双方节点上进行处理,而无需在路由器上处理。
- 会话层:负责建立和断开通信连接,以及数据的分割等数据传输相关的管理。
- 表示层:将应用处理的信息转换为适合网络传输的格式,或将来自下一层的数据转换为上层能够处理的格式。因此它主要负责数据格式的转换。
- 应用层:为应用程序提供服务并规定应用程序中通信相关的细节。包括文件传输、电子邮件、远程登陆等协议。
- 数据从A 的应用层往下走到物理层,会在每一层都会加上头部信息,进行封装,然后再发送到B。然后 Server B 从 最下面的物理层往上 每一层进行解封装,最后到达应用层,得到数据。
七层模型协议
层级模型 | 协议 |
---|---|
物理层 | IEE802.3(以太网),CLOCK RJ45 |
数据链路层 | MAC,PPP(点对点协议),SDLC(同步数据链路控制) |
网络层 | IP,RIP,ARP,ICMP |
传输层 | TCP,UDP |
会话层 | RPC,NFS |
表示层 | JPEG(关于图像),ASII |
应用层 | HTTP,HTTPS,FTP,DNS |
- 传输层协议DCCP是数据报拥塞控制协议是取代UDP的新传输协议,用来传输实时业务。它是一个可以进行拥塞控制的非可靠传输协议,并同时提供多种拥塞控制机制,在通信开始时由用户进行协商选择。
TCP/IP协议五层协议模型
硬件(物理层)
TCP/IP的最底层是负责数据传输的硬件,如以太网或者电话线路等物理设备。TCP/IP是在网络互联的设备之间能够通信的前提之下提出来的协议。
网络接口层(数据链路层)
网络接口层利用以太网中的数据链路层进行通信,因此属于接口层。也可以把它当作让NIC起作用的“驱动程序”。
互联网层(网络层)
互联网层使用IP协议,相当于OSI模型中的网络层。
TCP/IP分层中的互联网层和传输层的功能通常是由操作系统提供。尤其是路由器,它必须得实现通过互联网层转发分组数据包的功能。此外,链接互联网的所有主机和路由器都必须实现IP的功能,其他连接互联网的网络设备就没必要一定实现IP或TCP的功能。
传输层
传输层最主要的功能就是要实现应用程序之间的通信。计算机的内部,通常同一时间运行着多个程序。为此,我们必须分清哪些程序与哪些程序正在进行通信,识别这些应用程序的是端口号。
TCP
TCP是一种面向有连接的传输协议。优点在于安全性高,缺点在于多次发包收包会浪费网络流量。
UDP
UDP是一种面向无连接的传输协议。优点在于程序简单,缺点在于安全性低。
应用层(会话层以上的分层)
应用层就是规定应用进程在通信时所遵循的协议
TCP/IP的分层中,将OSI参考模型中的会话层、表示层、应用层的功能都集中到了应用程序中实现。
如下常见的应用程序:
WWW
浏览器与服务器之间通信所用的协议是HTTP,它属于OSI应用层的协议。
所传输数据的主要格式是HTML,它属于OSI表示层的协议。
电子邮件
发送电子邮件所用到的协议是SMTP,它只可以发送文本格式,后来电子邮件的格式由MIME协议扩展,就可以发送声音、图像等各种各样的信息。MIME也属于表示层的协议。
文件传输
文件传输指可以将其他计算机硬盘中的文件传输到本机上,或者相反的操作。文件传输所用的协议是FTP。
远程登录
远程登录是指登录到远程的计算机上,使那台计算机上的程序可以运行。
TCP/IP网络中远程登录常用TELNET和SSH两种协议。
网络管理
在TCP/IP中进行网络管理时,采用SNMP协议。使用SNMP管理的主机、网桥、路由器等称作SNMP代理,而进行管理的那一段叫做管理器。SNMP就是管理器和代理之间要用到的协议。
网络编程三要素
- IP地址
要想让网络中的计算进能够互相通信,必须为每台计算机指定一个标识号,通过这个标识号来指定要接收数据的计算机和识别发送的计算机,而IP地址就是这个标识号。也就是设备的标识
- 端口号
网络的通信,本质上是两个应用程序的通信,每台计算机都有很多的应用程序,那么在网络通信时,如何区分这些应用程序呢?如果说IP地址可以唯一标识网络中的设备,那么端口号就可以唯一标识设备中的应用程序了,也就是应用程序的标识
- 通信协议
通过计算机网络可以使多台计算机实现连接,位于同一个网络中的计算机在进行连接和通信时需要遵守一定的规则,这就好比在道路中行驶的汽车一定要遵守交通规则一样,在计算机网络中,这些连接和通信的规则被称为网络通信协议,它对数据的传输格式、传输速率、传输步骤等做了统一规定,通信双方必须同时遵守才能完成数据交换。常见的协议有UDP协议和TCP协议。
IP地址
IPv4
是给每个连接在网络上的主机分配一个32bit地址。按照TCP/IP规定,IP地址用二进制来表示,每个IP地址长32bit,也就是4个字节。例如一个采用二进制形式的IP地址是“11000000 10101000 00000001 0100000010”,这么长的地址,处理起来太费劲了,为了方便使用,IP地址经常被写成十进制的形式,中间使用符号“.”分隔不同的字节。于是,上面的IP地址可以表示为“192.168.1.66”。IP地址这种表示法叫做“点分十进制表示法”,这显然比1和0容易记忆得多
IPv6
由于互联网的蓬勃发展,IP地址的需求愈来愈大,但是网络地址资源有限,使用的IP分配越发紧张。为了扩大地址空间,通过IPv6重新定义地址空间,采用128位地址长度,每16个字节一组,分成8组十六进制数,这样就解决了网络地址资源数量不够的问题
常用命令
- ipconfig:查看本机IP地址
- ping IP地址:检查网络是否连通
- 特殊IP地址:192.0.0.1是回送地址,可以代表本机地址,一般用来测试使用
InetAddress的使用
- 为了方便我们对IP地址的获取和操作,Java提供了一个类InetAddress供我们使用
- InetAddress:此类表示Internet(IP)地址
- static InetAddress getByName(String host):确定注解名称的IP地址。主机名称可以是机器名称,也可以是IP地址
- String getHostName():获取此IP地址的主机名
- String getHostAddress():返回文本显示中的IP地址字符串
- 代码示例
public class Demo { public static void main(String [] args) throws Exception { // 根据主机名获取IP地址对象192.168.131.1 InetAddress address = InetAddress.getByName("邪灵"); // 根据ip地址获取IP地址对象192.168.131.1 InetAddress address1 = InetAddress.getByName("192.168.131.1"); // 主机名写localhost192.0.0.1 InetAddress add01 = InetAddress.getByName("localhost"); // 写域名也可 InetAddress add02 = InetAddress.getByName("www.baidu.com"); // 通过IP地址对象获取主机名 String name = address.getHostName(); // 通过IP地址对象获取ip地址 String addr = address.getHostAddress(); System.out.println("主机名:"+name); System.out.println("IP地址:"+addr); } }
InetSocketAddress的使用
- 封装了IP和端口
- 可以获取InetAddress对象
- 代码示例
public class Demo { public static void main(String [] args) { InetSocketAddress isa = new InetSocketAddress("localhost",8080); System.out.println(isa); System.out.println(isa.getHostName()); System.out.println(isa.getPort()); InetAddress address = isa.getAddress(); System.out.println(address.getHostName()); System.out.println(address.getHostAddress()); } }
端口
- 端口:设备上应用程序的唯一标识
- 端口号:两个字节表示的整数,它的取值范围是0-65535。其中,0-103之间的端口号用于一些知名的网络服务和应用,普通的应用程序需要使用1024以上的端口。如果端口被另外一个服务或者应用所占有,会导致当前程序启动失败。
传输协议
- 协议:计算机网络中,连接和通信的规则被称为网络通信协议
- IP地址和PORT(端口)只能用于定位(网络定位),以什么方式进行通信呢?写信、发Email、打电话、发短信、发微信…… 不同的通信方式,可靠性、及时性、安全性等很多方面都不同,这就是不同的传输协议
UDP
- 用户数据报协议(User Datagram Protocol)
- UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。
- 简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就是发送数据,同样接收端在收到数据时,也不会向发送端反馈是否接收到数据。
- 由于使用UDP协议消耗资源小,通信效率高,所以通常都会用于音频、视频、和普通数据的传输
- 例如视频会议通常采用UDP协议,因为这种情况即时偶尔丢失一两个数据包,也不是对接收结果产生太大影响。
- 但是在使用UDP协议传输数据时,由于UDP的面向无连接性,不能保证数据的完整性,因此在传输重要数据时,不建议使用UDP协议
- 快(只管发送消息,至于对方是否接收到,它不在乎) 在线视频(流媒体)
- 先后顺序不保证、丢包、数据不准确
TCP
- 传输控制协议(Transmission Control Protocol)
- TCP协议是面向连接的通信协议,即传输数据之前,在发送端和接收端建立逻辑连接,然后再传输数据
- 它提供了两台计算机之间可靠无差错的数据传输。在TCP连接中必须明确客户端与服务端,由客户端向服务端发出连接请求,每次连接的创建都需要经过“三次握手”
- 完成三次握手,连接建立后,客户端和服务器端就可以开始进行数据传输了。由于面向连接的特性,TCP协议可以保证传输数据的安全性,所以应用十分广泛。例如上传文件、下载文件、浏览网页等
- 断开连接需要四次挥手。
- 可靠(三次握手,四次挥手),确保先发的数据先到(数据的先后顺序不会错乱)
- 慢
张三 李四
----------------------你在吗------------------------>
<------------------听到了,我在--------------------
----------我知道你在了,开始通信吧---------->
数据传输中
-----------------------我说完了--------------------->
<-------------------我知道你发完了---------------
<--------------------我也发完了--------------------
---------------------我知道你发完了-------------->
TCP与UDP区别
- TCP是面向连接的,UDP是无连接的;
- TCP是可靠的,UDP是不可靠的;
- TCP只支持点对点通信,UDP支持一对一、一对多、多对一、多对多的通信模式;
- TCP是面向字节流的,UDP是面向报文的;
- TCP有拥塞控制机制;UDP没有拥塞控制,适合媒体通信;
- TCP首部开销(20个字节)比UDP的首部开销(8个字节)要大
三次握手
- TCP协议中,在发送数据的准备阶段,客户端与服务端之间的三次交互,以保证连接的可靠
- 第一次握手:客户端向服务器端发出连接请求,等待服务器确认
- 第二次握手:服务器端向客户端回送一个响应,通知客户端收到了连接请求
- 第三次握手:客户端再次向服务器端发送确认信息,确认连接
- 作用:确认双方的接收发送能力是否正常。
四次挥手
- 第一次挥手:客户端发送一个 FIN 报文,报文中会指定一个序列号。此时客户端处于FIN_WAIT1状态。
- 第二次握手:服务端收到 FIN 之后,会发送 ACK 报文,且把客户端的序列号值 + 1 作为 ACK 报文的序列号值,表明已经收到客户端的报文了,此时服务端处于 CLOSE_WAIT状态。
- 第三次挥手:如果服务端也想断开连接了,和客户端的第一次挥手一样,发给 FIN 报文,且指定一个序列号。此时服务端处于 LAST_ACK 的状态。
- 第四次挥手:客户端收到 FIN 之后,一样发送一个 ACK 报文作为应答,且把服务端的序列号值 + 1 作为自己 ACK 报文的序列号值,此时客户端处于 TIME_WAIT 状态。需要过一阵子以确保服务端收到自己的 ACK 报文之后才会进入 CLOSED 状态
Socket
- Socket可以看成在两个程序进行通讯连接中的一个端点的抽象,一个程序将一段信息写入Socket中,该Socket将这段信息发送给另外一个Socket中,使这段信息能传送到其他程序中
- 可以理解为是用来应用层获取传输层的协议
-
就是下图的手机
张三(iPhone XS Max) --------------------- (华为Mate 20 保时捷版)李四
话筒 -------------------------------------------------------------------------------------------> 听筒
听筒 <------------------------------------------------------------------------------------------- 话筒
-
演示:Client <–> Server
C/S架构 客户端/服务端 必须要安装客户端才能运行 QQ、LOL、网易云音乐客户端
B/S架构 浏览器/服务端 用户只需要安装一个浏览器即可 WebQQ、页游
通信程序
UDP通信程序
UDP通信原理
UDP协议是一种不可靠的网络协议,它在通信的两端各建立一个Socket对象,但是这两个Socket只是发送,接收数据的对象
因此对于基于UDP协议的通信双方而言,没有所谓的客户端和服务器端概念
Java提供了DatagramSocket类作为基于UDP协议的Socket
UDP发送数据
发送数据的步骤
- 创建发送端的Socket对象(DatagramSocket)
DatagramSocket() - 创建数据,并把数据打包
DatagramPacket(byte[]buf,int length,InetAddress address,int port) - 调用DatagramSocket对象的方法发送数据
void send(DatagramPacket p) - 关闭发送端
void close()
代码示例
public class UDPSend {
public static void main(String[] args) {
try {
// 创建发送的Socket对象(DatagramSocket)
DatagramSocket socket = new DatagramSocket();
// 创建数据,将数据打包
byte[] bytes = "你好呀!".getBytes(StandardCharsets.UTF_8);
DatagramPacket dp = new DatagramPacket(bytes,bytes.length, InetAddress.getByName("邪灵"),10086);
// 调用DatagramSocket的方法发送数据
socket.send(dp);
// 关闭发送端
socket.close();
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
UDP接收数据
UPD接收数据步骤
- 创建接收端的Socket对象(DatagramSocket)
DatagraSocket(int port) - 创建一个数据包,用于接收数据
DatagramPacket(byte[]buf,int length) - 调用DatagramSocket对象的方法接收数据
void receive(DatagramPacket p) - 解析数据包,并把数据在控制台显示
byte[] getDate():拿到数据缓冲区
int getLength():实际拿到的数据长度 - 关闭接收端
void close()
代码示例
public class UDPReceive {
public static void main(String[] args) {
try {
// 创建接收端的Socket对象(DatagramSocket)
DatagramSocket socket = new DatagramSocket(10086);
// 创建数据包,用于接收数据
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes,bytes.length);
// 调用socket的方法接收数据‘
socket.receive(dp);
// 解析数据
byte[] data = dp.getData();
// 获取实际接收到的数据长度
int length = dp.getLength();
// 将数据打印到控制台
String str = new String(data,0,length);
System.out.println("str = " + str);
// 关闭接收端
socket.close();
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
TCP通信程序
TCP通信原理
- TCP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket对象,从而在通信的两端形成网络虚拟链路,一旦建立了虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信
- Java对基于TCP协议的网络提供了良好的封装,使用Socket对象来代表两端的通信端口,并通过Socket产生IO流来进行网络通信
- Java为客户端提供了Socket类,为服务器端提供了ServerSocket类
TCP发送数据
TCP发送数据步骤
- 创建客户端的Socket对象(Socket)
Socket(String host,int port) - 获取输出流,写入数据
OutputStream getOutputStream() - 释放资源
void close()
代码示例
public class Client{
public static void main(String [] args){
//根基服务端地址与端口号获得socket对象
Socket socket = new Socket(InetAddress.getByName("localhost"),8888);
//获得socket的输入流对象,封装为缓冲流输入流对象,用来读取服务器端的数据
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//获取socket的输出流对象,用printWriter,自动刷新
PrintWriter pw = new PrintWriter(socket.getOutputStream(),true);
//获取标准键盘输入流,封装缓冲流
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
while (true){
//获取键盘输入的一行内容
String string = bufferedReader.readLine();
//输出流发送给服务器端
pw.println(string);
//输入流来读取服务器端的数据
string = br.readLine();
System.out.println("server say :"+string);
if ("BYE".equals(string)){
break;
}
}
//断开资源
System.out.println("断开连接");
br.close();
pw.close();
bufferedReader.close();
socket.close();
}
}
TCP接收数据
TCP接收数据步骤
- 创建服务器端的Socket对象(ServerSocket)
ServerSocket(int port) - 监听客户端连接,返回一个Socket对象
Socket accept() - 获取输入流,读数据,并把数据显示在控制台
InputStream getInputStream() - 释放资源
void close()
代码示例
public class TCPServer {
public static void main(String[] args) throws IOException {
//创建服务器端的socket对象,设置端口为8888,客户端连接是端口于此对应
ServerSocket serverSocket = new ServerSocket(8888);
//获取到客户端的请求
Socket socket = serverSocket.accept();
System.out.println(socket.getInetAddress()+"已经连接");
//与客户端对应的获取输入流与输出流,用来获取客户端的数据并向客户端发送数据
BufferedReader br =new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter pw = new PrintWriter(socket.getOutputStream(),true);
String string = "";
while ((string=br.readLine())!=null){
System.out.println("Clin say: "+string);
//读取一行数据输出到屏幕并转换为大写发送给客户端
pw.println(string.toUpperCase());
if ("over".equalsIgnoreCase(string))
break;
}
//释放资源
System.out.println("连接断开");
pw.close();
br.close();
socket.close();
}
}
URL
- 资源在网络世界中的地址(通俗地理解为网址)
- 所谓的网络资源、所谓的云其实都是硬盘里的文件,只不过这些硬盘不在咱们的电脑上,无法直接访问。需要通过网络访问百度、腾讯服务器上的数据
- 演示:下载mp3
- 谷歌中点击f12,然后点击f5刷新,点击disable cache,点击size,找到最后一般就是资源地址。
*JSON
-
格式 { “name” : “lanying” , “age” : 18 }
-
演示:K780天气预报
-
拼接URL
http://api.k780.com/?app=weather.future &weaid=1 &appkey=APPKEY &sign=SIGN &format=json http://api.k780.com/?app=weather.future&weaid=%E4%B8%8A%E6%B5%B7&appkey=15643&sign=39476c0fdaac478cafbe2659b3395a99&format=json 上海 %E4%B8%8A%E6%B5%B7
-
通过URL获取服务器返回的数据(JSON格式)
在https://www.json.cn/ 中查看JSON数据的结构,以便于下一步解析数据
-
解析JSON
导入org.json.xxx.jar (引入第三方的库) 目的是直接使用库中写好的类
-
以友好的方式返回给用户
-