目录
第17章 网络编程
17.1 软件结构
17.2 网络通信三要素
17.2.1 IP地址和域名
1、IP地址
2、域名
17.2.2 端口号
17.2.3 网络通信协议
17.3 TCP与UDP协议
17.3.1 UDP协议
17.3.2 TCP协议
1、三次握手
2、四次挥手
17.4 网络编程API
17.4.1 InetAddress类
17.4.2 Socket
17.4.3 Socket相关类AP
1、ServerSocket类
2、Sokcet类
17.4.2 开发步骤
17.4.3 演示客户端与服务器通信
1、服务器端示例代码
2、客户端示例代码
第17章 网络编程
17.1 软件结构
-
C/S结构 :全称为Client/Server结构,是指客户端和服务器结构。常见程序有qq等软件。 客户端就是我们手机上的APP、电脑下载的各种客户端软件比如各种大型网络游戏软件,服务器指的是实现数据操作功能的计算机。
-
B/S结构 :全称为Browser/Server结构,是指浏览器和服务器结构。常见浏览器有谷歌、IE等。
是WEB兴起后的一种网络结构模式,WEB浏览器是客户端最主要的应用软件。
两种架构各有优势,但是无论哪种架构,都离不开网络的支持。网络编程,就是在一定的协议下,实现两台计算机的通信的程序。
17.2 网络通信三要素
-
IP地址
InetAddress,网络中计算机的唯一标识,不易记忆,可用主机名。
-
端口号 用于标识进程的逻辑地址,不同进程的标识,netstat -ano
-
传输协议
通讯的规则,常见协议:TCP,UDP
17.2.1 IP地址和域名
1、IP地址
IP地址:指互联网协议地址(Internet Protocol Address),俗称IP。IP地址用来给一个网络中的计算机设备做唯一的编号。假如我们把“个人电脑”比作“一台电话”的话,那么“IP地址”就相当于“电话号码”。
IP地址分类方式一:
-
IPv4: 目前的全球因特网所采用的协议族是TCP/IP协议族。IP是TCP/IP协议族中网络层的协议,是TCP/IP协议族的核心协议。目前IP协议的版本号是4(简称为IPv4),是一个32位的二进制数,通常被分为4个字节,表示成
a.b.c.d
的形式,例如192.168.65.100
。其中a、b、c、d都是0~255之间的十进制整数。 -
IPv6:由于互联网的蓬勃发展,IP地址的需求量愈来愈大,但是网络地址资源有限,使得IP的分配越发紧张。
为了扩大地址空间,拟通过IPv6重新定义地址空间,采用128位地址长度,每16个字节一组,分成8组十六进制数,表示成
2001:3CA1:010F:001A:121B:0000:0000:0010
,
IP地址分类方式二:
公网地址( 万维网使用)和 私有地址( 局域网使用)。公网IP地址是全球唯一的IP地址,由互联网服务提供商(ISP)分配,用于连接到公共互联网的设备。公网IP地址可以被全球范围内的设备所访问,它们是互联网通信的重要标识之一。 私网IP地址是在局域网中使用的IP地址,用于局域网中的设备之间进行通信。私网IP地址不是全球唯一的,它们只在局域网内部有意义,不能被公共互联网所访问。私网IP地址的作用是在局域网中进行内部通信,而公网lIP地址的作用是在全球范围内进行通信。
常用命令:
-
查看本机IP地址,在控制台输入:
ipconfig
-
检查网络是否连通,在控制台输入:
ping 空格 IP地址 ping 192.168.21.39
特殊的IP地址:
-
本地回环地址(hostAddress):
127.0.0.1
-
主机名(hostName):
localhost
2、域名
因为IP地址数字不便于记忆,因此出现了域名,域名容易记忆,当在连接网络时输入一个主机的域名后,域名服务器(DNS)负责将域名转化成IP地址(域名解析),这样才能和主机建立连接。
17.2.2 端口号
网络的通信,本质上是两个进程(应用程序)的通信。每台计算机都有很多的进程,那么在网络通信时,如何区分这些进程呢?
如果说IP地址可以唯一标识网络中的设备,那么端口号就可以唯一标识设备中的进程(应用程序)了。
-
端口号:用两个字节表示的整数,它的取值范围是0~65535。
-
公认端口:0~1023。被预先定义的服务通信占用,如:HTTP(80),FTP(21),Telnet(23)
-
注册端口:1024~49151。分配给用户进程或应用程序。如:Tomcat(8080),MySQL(3306),Oracle(1521)。
-
动态/ 私有端口:49152~65535。
-
如果端口号被另外一个服务或应用所占用,会导致当前程序启动失败。
17.2.3 网络通信协议
-
网络通信协议:通过计算机网络可以使多台计算机实现连接,位于同一个网络中的计算机在进行连接和通信时需要遵守一定的规则,这就好比在道路中行驶的汽车一定要遵守交通规则一样。在计算机网络中,这些连接和通信的规则被称为网络通信协议,它对数据的传输格式、传输速率、传输步骤等做了统一规定,通信双方必须同时遵守才能完成数据交换。
-
TCP/IP协议: 传输控制协议/因特网互联协议( Transmission Control Protocol/Internet Protocol),是Internet最基本、最广泛的协议。它定义了计算机如何连入因特网,以及数据如何在它们之间传输的标准。它的内部包含一系列的用于处理数据通信的协议,并采用了4层的分层模型,每一层都呼叫它的下一层所提供的协议来完成自己的需求。
网络模型一般是指 OSI(Open System Interconnection)开放系统互连参考模型 TCP/IP(Transmission Control Protocol/Internet Protocol)传输控制协议/网际协议参考模型
【1】应用层: 主要是一些终端的应用,比如说FTP(各种文件下载),WEB(http,https),QQ之类的(可以把它理解成我们在电脑屏幕上可以看到的东西.就是终端应用)。
【2】表示层:主要是进行对接收的数据进行解释、加密与解密、压缩与解压缩等,另外表示层协定来保证不同的计算机可以彼此理解。
【3】会话层:会话层主要功能是管理和协调不同主机上各种进程之间的通信,即负责建立、管理和终止应用程序之间的会话。
【4】传输层:定义了一些传输数据的协议和端口号(WWW端口80等),如:TCP,UDP,常常把这一层数据叫做段
。
【5】网络层:在位于不同地理位置的网络中的两个主机系统之间提供连接和路径选择,而网络层正是管理这种连接的层。在这一层工作的设备是路由器
,常把这一层的数据叫做数据包。
【6】数据链路层:主要将从物理层接收的数据进行MAC地址(网卡的地址)的封装与解封装。常把这一层的数据叫做帧。在这一层工作的设备是交换机
,数据通过交换机来传输。
【7】物理层:主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质等。它的主要作用是传输比特流(就是由1、0转化为电流强弱来进行传输),这一层的数据叫做比特
。
17.3 TCP与UDP协议
通信的协议还是比较复杂的,java.net
包中包含的类和接口,它们提供低层次的通信细节。我们可以直接使用这些类和接口,来专注于网络程序开发,而不用考虑通信的细节。
java.net
包中提供了两种常见的网络协议的支持:
-
UDP协议
-
用户数据报协议(User Datagram Protocol)
-
UDP是面向无连接通信协议。
-
速度快,有大小限制一次最多发送64K,数据不安全,易丢失数据。
-
-
TCP协议
-
传输控制协议 (Transmission Control Protocol)
-
TCP协议是面向连接的通信协议。
-
速度慢,没有大小限制,数据安全
-
17.3.1 UDP协议
UDP:用户数据报协议(User Datagram Protocol),它是非面向连的,不可靠的无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。
17.3.2 TCP协议
TCP:传输控制协议 (Transmission Control Protocol)。它是面向连接的,可靠的通信协议,即传输数据之前,在发送端和接收端建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。是一种面向连接的、可靠的、基于字节流的传输层的通信协议,可以连续传输大量的数据。类似于打电话的效果。
这是因为它为当一台计算机需要与另一台远程计算机连接时,TCP协议会采用“三次握手”方式让它们建立一个连接,用于发送和接收数据的虚拟链路。数据传输完毕TCP协议会采用“四次挥手”方式断开连接。
1、三次握手
TCP协议中,在发送数据的准备阶段,客户端与服务器之间的三次交互,以保证连接的可靠。
-
第一次握手,客户端向服务器端发出连接请求,等待服务器确认。
-
第二次握手,服务器端向客户端回送一个响应,通知客户端收到了连接请求。
-
第三次握手,客户端再次向服务器端发送确认信息,确认连接。
完成三次握手,连接建立后,客户端和服务器就可以开始进行数据传输了。由于这种面向连接的特性,TCP协议可以保证传输数据的安全,所以应用十分广泛,例如下载文件、浏览网页等。
2、四次挥手
TCP协议中,在发送数据结束后,释放连接时需要经过四次挥手。
-
第一次挥手:客户端向服务器端提出结束连接,让服务器做最后的准备工作。此时,客户端处于半关闭状态,即表示不再向服务器发送数据了,但是还可以接受数据。
-
第二次挥手:服务器接收到客户端释放连接的请求后,会将最后的数据发给客户端。并告知上层的应用进程不再接收数据。
-
第三次挥手:服务器发送完数据后,会给客户端发送一个释放连接的报文。那么客户端接收后就知道可以正式释放连接了。
-
第四次挥手:客户端接收到服务器最后的释放连接报文后,要回复一个彻底断开的报文。这样服务器收到后才会彻底释放连接。这里客户端,发送完最后的报文后,会等待2MSL,因为有可能服务器没有收到最后的报文,那么服务器迟迟没收到,就会再次给客户端发送释放连接的报文,此时客户端在等待时间范围内接收到,会重新发送最后的报文,并重新计时。如果等待2MSL后,没有收到,那么彻底断开。
17.4 网络编程API
17.4.1 InetAddress类
InetAddress类主要表示IP地址,两个子类:Inet4Address、Inet6Address。
Internet上的主机有两种方式表示地址:
-
域名(hostName):www.haogu.com
-
IP 地址(hostAddress):205.108.36.20
lInetAddress 类没有提供公共的构造器,而是提供 了 如下几个 静态方法来获取InetAddress 实例
-
public static InetAddress getLocalHost()
-
public static InetAddress getByName(String host)
17.4.2 Socket
通信的两端都要有Socket(也可以叫“套接字”),是两台机器间通信的端点。网络通信其实就是Socket间的通信。Socket可以分为:
-
流套接字(stream socket):使用TCP提供可依赖的字节流服务
-
ServerSocket:此类实现TCP服务器套接字。服务器套接字等待请求通过网络传入。
-
Socket:此类实现客户端套接字(也可以就叫“套接字”)。套接字是两台机器间通信的端点。
-
17.4.3 Socket相关类AP
1、ServerSocket类
ServerSocket类的构造方法:
-
ServerSocket(int port) :创建绑定到特定端口的服务器套接字。
ServerSocket类的常用方法:
-
Socket accept():侦听并接受到此套接字的连接。
2、Sokcet类
Socket类的常用构造方法:
-
public Socket(InetAddress address,int port):创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
-
public Socket(String host,int port):创建一个流套接字并将其连接到指定主机上的指定端口号。
Socket类的常用方法:
-
public InputStream getInputStream():返回此套接字的输入流,可以用于接收消息
-
public OutputStream getOutputStream():返回此套接字的输出流,可以用于发送消息
-
public InetAddress getInetAddress():此套接字连接到的远程 IP 地址;如果套接字是未连接的,则返回 null。
-
public InetAddress getLocalAddress():获取套接字绑定的本地地址。
-
public int getPort():此套接字连接到的远程端口号;如果尚未连接套接字,则返回 0。
-
public int getLocalPort():返回此套接字绑定到的本地端口。如果尚未绑定套接字,则返回 -1。
-
public void close():关闭此套接字。套接字被关闭后,便不可在以后的网络连接中使用(即无法重新连接或重新绑定)。需要创建新的套接字对象。 关闭此套接字也将会关闭该套接字的 InputStream 和 OutputStream。
-
public void shutdownInput():如果在套接字上调用 shutdownInput() 后从套接字输入流读取内容,则流将返回 EOF(文件结束符)。 即不能在从此套接字的输入流中接收任何数据。
-
public void shutdownOutput():禁用此套接字的输出流。对于 TCP 套接字,任何以前写入的数据都将被发送,并且后跟 TCP 的正常连接终止序列。 如果在套接字上调用 shutdownOutput() 后写入套接字输出流,则该流将抛出 IOException。 即不能通过此套接字的输出流发送任何数据。
17.4.2 开发步骤
服务器端程序包含以下四个基本的步骤:
-
调用 ServerSocket(int port) :创建一个服务器端套接字,并绑定到指定端口上。用于监听客户端的请求。
-
调用 accept() :监听连接请求,如果客户端请求连接,则接受连接,返回通信套接字对象。
-
调用 该Socket 类对象的 getOutputStream() 和 getInputStream () :获取输出流和输入流,开始网络数据的发送和接收。
-
关闭Socket 对象:客户端访问结束,关闭通信套接字。
客户端程序包含以下四个基本的步骤 :
-
创建 Socket :根据指定服务端的 IP 地址或端口号构造 Socket 类对象。若服务器端响应,则建立客户端到服务器的通信线路。若连接失败,会出现异常。
-
打开连接到 Socket 的输入/ 出流: 使用 getInputStream()方法获得输入流,使用getOutputStream()方法获得输出流,进行数据传输
-
按照一定的协议对 Socket 进行读/ 写操作:通过输入流读取服务器放入线路的信息(但不能读取自己放入线路的信息),通过输出流将信息写入线路。
-
关闭 Socket :断开客户端到服务器的连接,释放线路
17.4.3 演示客户端与服务器通信
需求:客户端连接服务器,连接成功后给服务发送“hello”,服务器收到消息后,给客户端返回“欢迎登录”,客户端接收消息后,断开连接
1、服务器端示例代码
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args)throws Exception {
//1、准备一个ServerSocket对象,并绑定8888端口
ServerSocket server = new ServerSocket(8888);
System.out.println("等待连接....");
//2、在8888端口监听客户端的连接,该方法是个阻塞的方法,如果没有客户端连接,将一直等待
Socket socket = server.accept();
InetAddress inetAddress = socket.getInetAddress();
System.out.println(inetAddress.getHostAddress() + "客户端连接成功!!");
//3、获取输入流,用来接收该客户端发送给服务器的数据
InputStream input = socket.getInputStream();
//接收数据
byte[] data = new byte[1024];
StringBuilder s = new StringBuilder();
int len;
while ((len = input.read(data)) != -1) {
s.append(new String(data, 0, len));
}
System.out.println(inetAddress.getHostAddress() + "客户端发送的消息是:" + s);
//4、获取输出流,用来发送数据给该客户端
OutputStream out = socket.getOutputStream();
//发送数据
out.write("欢迎登录".getBytes());
out.flush();
//5、关闭socket,不再与该客户端通信
//socket关闭,意味着InputStream和OutputStream也关闭了
socket.close();
//6、如果不再接收任何客户端通信,可以关闭ServerSocket
server.close();
}
}
2、客户端示例代码
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws Exception {
// 1、准备Socket,连接服务器,需要指定服务器的IP地址和端口号
Socket socket = new Socket("127.0.0.1", 8888);
// 2、获取输出流,用来发送数据给服务器
OutputStream out = socket.getOutputStream();
// 发送数据
out.write("hello".getBytes());
//会在流末尾写入一个“流的末尾”标记,对方才能读到-1,否则对方的读取方法会一致阻塞
socket.shutdownOutput();
//3、获取输入流,用来接收服务器发送给该客户端的数据
InputStream input = socket.getInputStream();
// 接收数据
byte[] data = new byte[1024];
StringBuilder s = new StringBuilder();
int len;
while ((len = input.read(data)) != -1) {
s.append(new String(data, 0, len));
}
System.out.println("服务器返回的消息是:" + s);
//4、关闭socket,不再与服务器通信,即断开与服务器的连接
//socket关闭,意味着InputStream和OutputStream也关闭了
socket.close();
}
}
即时通讯webSocket:全双工通信,基与TCP协议.一般即时通讯软件,客服服务,即时更新的需求