41 网络编程
功能:让程序与网络上的其他设备中的程序进行数据交互。
网络通信基本模式:Client-Server(CS) 、 Browser/Server(BS)
1 Client-Server(CS)
Client 客户端,需要程序员开发实现。 用户需要安装客户端。
Server 服务端,需要程序员开发实现。
2 Browser/Server(BS)
Browser 浏览器:不需要程序员开发实现。 用户需要安装浏览器。
Server 服务端:需要程序员开发实现。
41.1 网络编程三要素
IP地址:设备在网络中的地址,是唯一的标识。
【可以理解为门牌号,省市区-路-小区-楼栋-单元-几零几】
端口:应用程序在设备中唯一的标识。
【可以理解为在这个门牌号里面的人中具体是那一个人,工号,学号这种】
协议: 数据在网络中传输的规则,常见的协议有UDP协议和TCP协议。
【场景理解:假设我用电脑发送数据给桂先生告诉他速食荞麦面卖完了,要不要吃速冻水饺,那么传输消息的协议就需要IP地址(找到桂先生的手机)和端口号(用QQ软件)】
【在不同的手机里面,同样的APP的端口号是一样的】
41.2 IP地址
定义:IP(Internet Protocol):全称”互联网协议地址”,是分配给上网设备的唯一标志。
常见的IP分类为:IPv4和IPv6
IPv4:其有四个字节也就是38bit 用点分十进制表示法表示
11000000 10101000 00000001 01000010 表示为192.168.1.66
IPv6:128位(16个字节)
分成8个整数,每个整数用四个十六进制位表示, 数之间用冒号(:)分开。
00100000 00000001 00001101 10111000 00000000 00000000 这种 表示为
ABCD:EF01:2345
IP地址形式:
公网地址和私有地址(局域网使用)。
192.168. 开头的就是常见的局域网地址,范围即为192.168.0.0--192.168.255.255,专门为组织机构内部使用。
IP常用命令:
ipconfig:查看本机IP地址
ping IP地址:检查网络是否连通
特殊IP地址:
本机IP: 127.0.0.1或者localhost:称为回送地址也可称本地回环地址,只会寻找当前所在本机。
IP地址操作类-InetAddress
此类表示Internet协议(IP)地址。
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 |
1.获取本机地址对象
InetAddress ip1 = InetAddress.getLocalHost();
都是用类调用方法
2.获取域名ip对象
InetAddress ip2 = InetAddress.getByName("www.baidu.com");
3.获取公网ip对象
InetAddress ip3 = InetAddress.getByName("36.152.44.96");
4.判断是否互通 ping 5s之内测试是否可通
System.out.println(ip3.isReachable(5000));//true
41.3 端口号
定义:标识正在计算机设备上运行的进程(程序),被规定为一个16位的二进制,范围是 0~65535。
分类:
- 周知端口:0~1023,被预先定义的知名应用占用(如:HTTP占用 80,FTP占用21)
- 注册端口:1024~49151,分配给用户进程或某些应用程序。(如:Tomcat占 用8080,MySQL占用3306)
- 动态端口:49152到65535,之所以称为动态端口,是因为它 一般不固定分配某种进程,而是动态分配。
注意:我们自己开发的程序选择注册端口,且一个设备中不能出现两个程序的端口号一样,否则出错。
41.4 协议
定义:连接和通信数据的规则被称为网络通信协议
参考模型:
1.OSI参考模型:世界互联协议标准,全球通信规范,由于此模型过于理想化,未能在因特网上进行广泛推广。
2.TCP/IP参考模型(或TCP/IP协议):事实上的国际标准。
OSI参考模型 |
TCP/IP参考模型 |
各层对应 |
面向操作 |
应用层 |
应用层 |
HTTP、FTP、DNS、SMTP… |
应用程序需要关注的:浏览器,邮箱。 程序员一般在这一层开发 |
表示层 |
|||
会话层 |
|||
传输层 |
传输层 |
TCP、UDP… |
选择使用的TCP , UDP协议 |
网络层 |
网络层 |
IP、ICMP… |
封装源和目标IP,进行路径选择 |
数据链路层 |
数据链路层+物理 |
物理寻址、比特流… |
物理设备中传输 |
其中:
传输层的2个常见协议:
TCP(Transmission Control Protocol) :传输控制协议
UDP(User Datagram Protocol):用户数据报协议
TCP协议特点:
- 使用TCP协议,必须双方先建立连接,它是一种面向连接的可靠通信协议。
- 传输前,采用“三次握手”方式建立连接,所以是可靠的 。
- 在连接中可进行大数据量的传输 。
- 连接、发送数据都需要确认,且传输完毕后,还需释放已建立的连接,通信效率较低。
“三次握手”:
- 客户端向服务器发出连接请求,等待服务器确认
- 服务器向客户端返回一个响应,告诉客户端收到了请求
- 客户端向服务器再次发出确认信息,连接建立
“TCP四次挥手断开连接”
- 客户端向服务器发出取消连接请求
- 服务器向客户端返回一个响应,表示收到客户端取消请求[服务器将最后的数据 处理完毕
- 服务器向客户端发出确认取消信息
- 客户端再次发送确认消息,连接取消
TCP协议通信场景 :对信息安全要求较高的场景,例如:文件下载、金融等数据通信。
41.4.1UDP协议:
UDP是一种无连接、不可靠传输的协议。
将数据源IP、目的地IP和端口封装成数据包,不需要建立连接
每个数据包的大小限制在64KB内
发送不管对方是否准备好,接收方收到也不确认,故是不可靠的
可以广播发送 ,发送数据结束时无需释放资源,开销小,速度快。
UDP协议通信场景 语音通话,视频会话等。
如何理解UDP协议通信模型?
假设AB两人在打沙包,A将沙包抛到B的手中,就是一次通信。
其中:
DatagramPacket:数据包对象【可以看做AB两人的手掌】
构造器 |
功能 |
public DatagramPacket(byte[] buf, int length, InetAddress address, int port) |
创建发送端数据包对象 buf:要发送的内容,字节数组 length:要发送内容的字节长度 address:接收端的IP地址对象 port:接收端的端口号 |
public DatagramPacket(byte[] buf, int length) |
创建接收端的数据包对象 buf:用来存储接收的内容 length:能够接收内容的长度 |
DatagramPacket常用方法
方法 |
功能 |
public int getLength() |
获得实际接收到的字节个数 |
DatagramSocket:发送端和接收端对象【可以看做AB两人】
构造器 |
功能 |
public DatagramSocket() |
创建发送端的Socket对象,系统会随机分配一个端口号。 |
public DatagramSocket(int port) |
创建接收端的Socket对象并指定端口号 |
DatagramSocket类成员方法
方法 |
功能 |
public void send(DatagramPacket dp) |
发送数据包 |
public void receive(DatagramPacket p) |
接收数据包 |
沙包就可以看做要传输的数据
小案例题:模拟使用UDP通信实现发送消息接收消息的过程
解题思路:
这个过程需要有发送端与接收端
每个端都需要一个“人”
每人都需要“手掌”
使用Send和receive方法发送接受
最后释放资源
注意要点:
接受端中,数据包对象(手掌)的大小建议设置为1024*64
读取数据的时候还应该“读多少倒多少”
小案例题:
模拟使用UDP通信实现发送消息接收消息的过程,但是要一直发消息一直接收消息
解题思路:在上一题的基础之上,使用死循环和扫描器即可。
UDP的接收端为什么可以接收很多发送端的消息?
接收端只负责接收数据包,无所谓是哪个发送端的数据包.
【人的手可以随便接任何人扔出来的沙包】
UDP的三种通信方式
单播:单台主机与单台主机之间的通信。
广播:当前主机与所在网络中的所有主机通信。
组播:当前主机与选定的一组主机的通信。
UDP实现广播案例:
- 发送端发送的数据包的目的地写的是广播地址、且指定端口。 (255.255.255.255 , 9999)
- 本机所在网段的其他主机的程序只要注册对应端口就可以收到消息了。(9999)
UDP实现组播案例:
- 发送端的数据包的目的地是组播IP (例如:224.0.1.1, 端口:9999)
- 接收端必须绑定该组播IP(224.0.1.1),端口还要注册发送端的目的端口9999 ,这样即可接收该组播消息。
- DatagramSocket的子类MulticastSocket可以在接收端绑定组播IP。
41.4.2 TCP协议
TCP通信模式:
在客户端与服务端之间使用Socket,通过字节输入流字节输出流进行信息的传递
注意:在java中只要是使用java.net.Socket类实现通信,底层即是使用了TCP协议
Socket
构造器 |
功能 |
public Socket(String host , int port) |
创建发送端的Socket对象与服务端连接,参数为服务端程序的ip和端口。 |
Socket类成员方法
方法 |
功能 |
OutputStream getOutputStream() |
获得字节输出流对象 |
InputStream getInputStream() |
获得字节输入流对象 |
ServerSocket(服务端)
构造器 |
功能 |
public ServerSocket(int port) |
注册服务端端口 |
ServerSocket类成员方法
方法 |
说明 |
public Socket accept() |
等待接收客户端的Socket通信连接 连接成功返回Socket对象与客户端建立端到端通信 |
小案例题:
模拟TCP协议的消息发送与接收
解题思路:
需要客户端与服务端
在客户端1.创建socket通信管道请求有服务端的连接【需要端口与ip】
2.从socket通信管道中得到一个字节输出流,负责发送数据【socket.getOutputStream()】
3.把低级字节楼包装成打印流【因为从输出的角度来讲,打印流最高效】
PrintStream ps = new PrintStream(os);
4.发送消息
ps.println("");
在服务端1.注册端口【serverSocket】
2.必须调用accept方法,等待接收客户端的Socket
3.从socket通信管道中得到一个字节输入流
4.把字节输入流包装成缓冲字符输入流进行消息的接受【相对高效】
5.按照行读取消息
小案例题:
使用TCP通信方式实现:多发多收消息。
解题思路:
在上一题的基础上使用死循环与扫描器
这种多发多收是否可以同时接收多个客户端的消息??
不行
目前服务端是单线程的,每次只能处理一个客户端的消息。
同时处理多个客户端消息
实现方法:
主线程定义了循环负责接收客户端Socket管道连接
每接收到一个Socket通信管道后分配一个独立的线程负责处理它。
小案例题:实现同时处理多个客户端消息
解题思路:
1.客户端与之前没有太大变化
2.服务端定义一个死循环,不断接受socket连接请求,每接收到一个socket管道就交给独立的子线程负责读取
那么此处需要用到多线程
定义一个线程,继承thread
成员变量就应该是socket类型
应该给一个有参构造器
run方法中的内容与之前编写的服务端类似
其中,若想有下线提示,我可以将下线提示写在try/catch的catch中,当客户端关闭之后,服务器接收不到消息就报错,刚好用来做下线的逻辑
由于上一题中客户端与服务端的线程模型是: N-N的关系,当客户端