一、软件结构
(1)Client/Server(C/S结构)
客户端/服务器的软件结构,例如QQ、微信、网盘客户端等,只要是需要我们下载安装,并且和服务器通信的这一类软件,都属于C/S的软件结构。
(2)Browser/Server(B/S结构)
浏览器/服务器的软件结构,例如淘宝网、京东商城等,只要是需要使用浏览器,并且和服务器通信的这一类软件,都属于B/S的软件结构
(3)C/S和B/S各有优势:
- C/S在图形的表现能力上以及运行的速度上一般是强于B/S的
- C/S需要运行专门的客户端,并且它不能跨平台,用c++在windows下写的程序一般是不能在linux下运行
- B/S不需要专门的客户端,只要系统中安装了浏览器即可访问,方便用户的使用。
- B/S是基于网页语言的、与操作系统无关,所以跨平台也是它的优势
二、通信协议
- 通过计算机网络可以使多台计算机实现相互连接,位于同一个网络中的两台计算机,在进行连接和通信时,需要遵守一定的规则,这些连接和通信的规则就是网络通信协议。
- TCP/IP协议栈,它是一系列网络协议的总和,是构成网络通信的核心骨架。它定义了计算机如何连入因特网,以及数据如何在计算机之间进行传输。
- TCP/IP协议栈采用4层结构,分别是应用层、传输层、网络层、链路层,并且在每一层的内部,都包含了一系列用于处理数据通信的协议,分别负责不同的通信功能。
- 链路层:链路层是用于定义物理传输通道,通常是对某些网络连接设备的驱动协议,例如针对光纤、网线提供的驱动。
- 网络层:网络层是整个TCP/IP协议的核心,它主要用于将传输的数据进行分组,将分组数据发送到目标计算机或者网络。
- 传输层:主要使网络程序进行通信,在进行网络通信时,可以采用TCP协议,也可以采用UDP协议。
- 应用层:主要负责应用程序的协议,例如HTTP协议、FTP协议等。
三、TCP和UDP
- java.net 包中对常见的俩种通信协议进行了封装和支持:
- UDP,用户数据报协议(User Datagram Protocol)
- UDP是无连接通信协议,在数据传输时,数据的发送端和接收端不建立连接,也不能保证对方能接收成功。
例如,当一台计算机向另外一台计算机发送数据时(UDP),发送端不会确认接收端是否存在,就会直接发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。 - 由于使用UDP协议消耗资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输,因为这种情况即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。
但是在传输重要数据时,不建议使用UDP协议,因为它不能保证数据传输的完整性。
- UDP是无连接通信协议,在数据传输时,数据的发送端和接收端不建立连接,也不能保证对方能接收成功。
- TCP,传输控制协议 (Transmission Control Protocol) (重要)
- TCP协议是面向连接的通信协议,即传输数据之前,在发送端和接收端建立连接,然后再传输数据,它提供了两台计算机之间可靠的、无差错的数据传输。
在TCP连接中,将计算机明确划分为客户端与服务器端,并且由客户端向服务端发出连接请求,每次连接的创建都需要经过“三次握手”的过程。
- TCP协议是面向连接的通信协议,即传输数据之前,在发送端和接收端建立连接,然后再传输数据,它提供了两台计算机之间可靠的、无差错的数据传输。
- UDP,用户数据报协议(User Datagram Protocol)
- TCP的三次握手:TCP协议中,在发送数据的准备阶段,客户端与服务器之间的三次交互,以保证连接的可靠
- 第一次握手,客户端向服务器端发出连接请求,等待服务器确认
- 第二次握手,服务器端向客户端回送一个响应,通知客户端收到了连接请求
- 第三次握手,客户端再次向服务器端发送确认信息,确认连接
四、 IP和端口号
(1)IP地址:互联网协议地址
IP地址用来给一个网络中的计算机设备做唯一的编号
查看本机IP地址的命令:
ipconfig
查看本机与另一台主机是否连通:ping ip地址
或ping 10.0.1.129
表示本机IP地址:127.0.0.1
或者localhost
(2)端口号:网络的通信,本质上是两个进程(应用程序)的通信。
- 每台计算机都有很多的进程,每个需要网络通信的进程(应用程序),都会占用系统的一个端口号。
- 在网络中,通过IP可以找到对应的主机设备,而通过端口号,可以找到这个主机中正在运行的一个应用程序
- 端口号的取值范围是0 ~ 65535。
- 0~1023之间的端口号用于系统内部的使用,
- 我们自己普通的应用程序要使用1024以上的端口号即可,同时也要避免和一些知名应用程序默认的端口冲突
oracle启动后默认占用端口号:1521
mysql启动后默认占用端口号:3306
redis启动后默认占用端口号:6379
tomcat启动后默认占用端口号:8080
SSH:22
FTP:21
HDFS:9870/50070
YARN:8088
五、TCP网络编程
在TCP通信协议下,能实现两台计算机之间的数据交互,并且它们要严格区分客户端(Client)与服务端(Server)
客户端和服务端通信的步骤:
- 服务端先进行启动,并占用一个指定的端口号,等待客户端的连接
- 客户端主动发起服务端的连接,在连接成功之后,就可以进行数据发送了
在整个过程中,服务端不能主动连接客户端,必须由客户端先行发起连接才行
对于这样基于TCP协议下连接通信的客户端和服务端,分别进行了抽象:
java.net.Socket
类表示客户端java.net.ServerSocket
类表示服务端
1.客户端
public static void main(String[] args){
//创建Socket对象,连接服务器,服务器地址是127.0.0.1,端口号是8888
Socket client = new Socket("127.0.0.1", 8888);
//使用out,可以给对方服务器写数据
OutputStream out = client.getOutputStream();
//使用in,可以读取对方服务器写回来的数据
InputStream in = client.getInputStream();
}
2.服务端
ServerSocket server = new ServerSocket(8888);
//accept方法会导致线程阻塞到这,等待客户端的连接
Socket socket = server.accept();
//使用out,可以给对方客户端写数据
OutputStream out = socket.getOutputStream();
//使用in,可以读取对方客户端发送过来的数据
InputStream in = socket.getInputStream();
3.交互
使用客户端(Socket)与服务端(ServerSocket)交互:
- 客户端和服务端进行连接
- 连接出成功后,客户端向服务器发送信息,服务器接收信息
- 连接出成功后,客户端向服务器发送信息,服务器接收信息,并且写回数据给客户端,客户端再接收
- 在当前基础上,修改客户端代码,让客户端可以从控制台接收用户的输入内容,然后再写给服务器,然后再接收服务器写回来的数据
六、UDP网络编程
- 在UDP通信协议下,两台计算机之间进行数据交互,并不需要先建立连接,客户端直接往指定的IP和端口号上发送数据即可,但是它并不能保证数据一定能让对方收到。
- 客户端和服务器端都使用的俩类:
java.net.DatagramSocket
负责接收和发送数据java.net.DatagramPacket
负责封装要发送的数据和接收到的数据
七、URI和URL
- URI(uniform resource identifier),统一资源标识符,用来唯一的标识一个资源。
- URL(uniform resource locator),统一资源定位符,它是一种具体的URI,即URL可以用来标识一个资源,而且还指明了如何定位这个资源。
java.net.URL
可以表示一个URL地址,使用URL对象打开一个连接后,可以获取这个网络资源返回的内容
public static void main(String[] args) {
try {
URL url = new URL("https://www.jd.com");
//打开这个URL的连接,强制为HttpURL的连接对象
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
//设置请求方式
httpConn.setRequestMethod("GET");
//模拟浏览器发送的请求的情况
httpConn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:79.0)
Gecko/20100101 Firefox/79.0");
//获取这个URL连接的输入流,准备读取数据
InputStream is = httpConn.getInputStream();
//字节流转换为字符流
Reader in = new InputStreamReader(is);
char[] cbuf = new char[1024];
int len = -1;
while ((len = in.read(cbuf)) != -1) {
System.out.print(new String(cbuf, 0, len));
}
} catch (IOException e) {
e.printStackTrace();
}
}