目录
1、网络编程
1.1、概述
1.1、网络编程三要素
2、UDP通信
2.1、DatagramPacket 与 DatagramSocket
2.1、 UDP发收数据示例
1、网络编程
1.1、概述
在网络通信协议下,不同计算机上运行的程序,进行的数据传输应用场景:即时通信、网游对战、金融证券、国际贸易、邮件、等等不管是什么场景,都是计算机跟计算机之间通过网络进行数据传输。Java中可以使用java.net包下的技术轻松开发出常见的网络应用程序。
学习网络编程,你需要掌握基础的网络基础知识,如三次握手和四次挥手的过程以及各个状态值,我建议使用 tcpdump 命令实际抓下包就一目了然了,然后就是网络分层,各层的用途,重点熟悉下 TCP/IP 层相关的知识,还有就是 TCP/UDP 的区别,TCP 的滑动窗口机制、拥塞控制算法、TCP 的保序、重传、确认机制。
网络中常见的软件架构:
C/S:Client/Server(客户端/服务器)在用户本地需要下载并安装客户端程序在远程有一个服务器端程序
CS架构的优缺点
- 优点:画面可以做的非常精美,用户体验好
- 缺点:需要开发客户端,也需要开发服务端;用户需要下载和更新的时候太麻烦
B/S:Browser/Server(浏览器/服务器)只需要一个浏览器,用户通过不同的网址,客户访问不同的服务器
BS架构的优缺点
- 优点:不需要开发客户端,只需要页面+服务端;用户不需要下载,打开浏览器就能使用
- 缺点:如果应用过大,用户体验受到影响
1.1、网络编程三要素
网络编程三要素是:IP;端口;协议
(1)IP
IP的作用
设备在网络中的地址,是唯一的标识
IPv4有什么特点
目前的主流方案最多只有2^32次方个ip,目前已经用完了
IPv6有什么特点
为了解决IPv4不够用而出现的最多有2^128次方个ip,可以为地球上的每一粒沙子都设定ip
IPv4的地址分类形式
公网地址(万维网使用)和私有地址(局域网使用)
192.168.开头的就是私有址址,范围即为192.168.0.0--192.168.255.255,专门为组织机构内部使用,以此节省IP
特殊IP地址
127.0.0.1(永远表示本机),也可以是localhost:是回送地址也称本地回环地址,也称本机IP,永远只会寻找当前所在本机。
疑问:假设192.168.1.100 是我电脑的IP,那么这个IP跟127.0.0.1是一样的吗? 不一样
如果是我电脑I的P是:192.168.1.100 然后我往 192.168.1.100 发送数据,它会先发送到路由器,然后再发回192.168.1.100 也就是我的电脑;而我往 127.0.0.1 发送数据时,它是不经过路由器的,当数据在经过网卡时,网卡发现要往 127.0.0.1 发送数据,网卡就会自己发这个数据发回来了
常用的CMD命令
ipconfig:查看本机IP地址ping:检查网络是否连通
InetAddress类的使用
static InetAddress getByName(string host)
确定主机名称的IP地址。主机名称可以是机器名称,也可以是IP地址
String getHostName()
获取此IP地址的主机名
String getHostAddress()
返回文本显示中的IP地址字符串
注意:确定主机名称的IP地址。主机名称可以是机器名称,也可以是IP地址,下面的代码中我用的是我自己的主机名称创建的ip对象,看主机名称的方式为,点击桌面上
的此电脑,鼠标右击选择属性,然后就可以找到主机名称了
方法示例:
public class MyInetAddressDemo {
public static void main(String[] args) throws UnknownHostException {
//1.获取InetAddress的对象,IP的对象 一台电脑的对象
InetAddress address = InetAddress.getByName("**********");//**********就是上面查到主机名
System.out.println(address);
String name = address.getHostName();
System.out.println(name);
String ip = address.getHostAddress();
System.out.println(ip);
}
}
(2)端口号
端口号是应用程序在设备中唯一的标识。
端口号:由两个字节表示的整数,取值范围:0~65535其中0~1023之间的端口号用于一些知名的网络服务或者应用我们自己使用1024以上的端口号就可以了。
注意:一个端口号只能被一个应用程序使用
(3)协议
计算机网络中,连接和通信的规则被称为网络通信协议
OSI参考模型:世界互联协议标准,全球通信规范,单模型过于理想化,未能在因特网上进行广泛推广
TCP/IP参考模型(或TCP/IP协议):事实上的国际标准。
在OSI七层模型中,应用app的代码都是运行在应用层的,如果两个主机之间要发送数据,就会把数据从应用层一层层的往下封装成物理层的比特包,然后通过物理层的传输介质到达目的主机的物理层,然后再把在物理层的比特包一层一层的往上解封装,然后把数据在应用层表示出来。(这个数据的整个传输过程还有如多其他的过程,这里我把他们都透明化了,有兴趣的可以自行去查看相关资料)
UDP协议
用户数据报协议(User Datagram Protocol)
UDP是面向无连接通信协议。
速度快,有大小限制一次最多发送64K,数据不安全,易丢失数据
TCP协议
传输控制协议TCP(Transmission control Protocol)
TCP协议是面向连接的通信协议。
速度慢,没有大小限制,数据安全,
2、UDP通信
2.1、DatagramPacket 与 DatagramSocket
DatagramSocket 类用于表示发送和接收数据报包的套接字。数据报包套接字是包投递服务的发送或接收点。每个在数据报包套接字上发送或接收的包都是单独编址和路由的。从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。
java.net 包中的 DatagramPacket 类用来表示数据报包,数据报包用来实现无连接包投递服务。每条报文仅根据该包中包含的信息从一台机器路由到另一台机器。从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。
2.1、 UDP发收数据示例
(1)发送数据
创建发送端的Datagramsocket对象
数据打包(DatagramPacket)
发送数据
释放资源
UDP发送数据示例:
public class SendMessageDemo {
public static void main(String[] args) throws IOException {
//1.创建DatagramSocket对象
// 注意:
// 绑定端口,以后我们就是通过这个端口往外发送
// 空参:所有可用的端口中随机一个进行使用
// 有参:指定端口号进行绑定
DatagramSocket ds = new DatagramSocket();
//2.打包数据
String str = "你能收到信息吗!!!";
byte[] bytes = str.getBytes();
InetAddress address = InetAddress.getByName("127.0.0.1");
int port = 10086;//绑定端口
DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, port);
//3.发送数据
ds.send(dp);
//4.释放资源
ds.close();
}
}
(2)接收数据
创建接收端的DatagramSocket对象
接收打包好的数据
解析数据包
释放资源
UDP接收数据示例:
public class ReceiveMessageDemo {
public static void main(String[] args) throws IOException {
//接收信息
//1.创建Datagramsocket对象
// 注意:
// 在接收的时候,一定要绑定端口
// 而且绑定的端口一定要跟发送的端口保持一致
DatagramSocket ds = new DatagramSocket(10086);//绑定端口
//2.接收数据包
//创建用于接收数据的数据包
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
//该方法是会自动阻塞在这里的,程序执行到这一步的时候,会在这里死等
//等发送端发送消息
ds.receive(dp);
//3.解析数据包
byte[] data = dp.getData();//获取数据包dp中的数据
int len = dp.getLength();//获取这次收到了多少个字节的数据
InetAddress address = dp.getAddress();//获取数据的源IP地址
int port = dp.getPort();//获取数据的源端口地址,由于在发送端没有指定端口,所以这里的端口是随机的
System.out.println("接收到数据" + new String(data,0,len));
//因为字节数组data的长度是1024,太大了,所以要用到这次收到了多少个字节的数据个数len来决定把字节数组data中的多少数据转换成字符串
System.out.println("该数据是从" + address + "这台电脑中的" + port + "这个端口发出来的!");
//4.释放资源
ds.close();
}
}
在运行的时候要先运行接收端的代码,再运行发送端的代码
运行结果:
注意:在上面的示例中,我在创建发送端的网络接口时没有指定使用哪一个端口,它就会在所有可用的端口中随机一个进行使用,这是不影响的,但是在创建发送数据的数据包时我指定了10086端口,所以我在创建接收端的网络接口时要指定使用10086端口来接收,不然就会接收不到数据了。而且这里的接收端代表的是聊天室这个平台,是一个服务器一样的存在,服务器是不会关闭的,比如淘宝、京东这些,它们要一直开着等待客户去访问的。
推荐:
【java多线程】线程池 ThreadPoolExecutor类和Executors工厂类以及线程池的最优大小_threadpool 线程池工厂类-CSDN博客https://blog.csdn.net/m0_65277261/article/details/137673188?spm=1001.2014.3001.5501
【Spring】依赖注入(DI)时常用的注解@Autowired和@Value-CSDN博客https://blog.csdn.net/m0_65277261/article/details/137784706?spm=1001.2014.3001.5501
【java多线程】通过等待唤醒机制、局部变量、原子变量实现线程同步-CSDN博客https://blog.csdn.net/m0_65277261/article/details/137122461?spm=1001.2014.3001.5501