【Java网络编程】网络编程概述、UDP通信(DatagramPacket 与 DatagramSocket)

目录

1、网络编程

1.1、概述

1.1、网络编程三要素

2、UDP通信

[2.1、DatagramPacket 与 DatagramSocket](#2.1、DatagramPacket 与 DatagramSocket)

[2.1、 UDP发收数据示例](#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对象,看主机名称的方式为,点击桌面上

的此电脑,鼠标右击选择属性,然后就可以找到主机名称了

方法示例:

java 复制代码
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发送数据示例:

java 复制代码
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接收数据示例:

java 复制代码
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

相关推荐
JaguarJack1 小时前
FrankenPHP 原生支持 Windows 了
后端·php·服务端
BingoGo1 小时前
FrankenPHP 原生支持 Windows 了
后端·php
JaguarJack1 天前
PHP 的异步编程 该怎么选择
后端·php·服务端
BingoGo1 天前
PHP 的异步编程 该怎么选择
后端·php
JaguarJack2 天前
为什么 PHP 闭包要加 static?
后端·php·服务端
ServBay3 天前
垃圾堆里编码?真的不要怪 PHP 不行
后端·php
用户962377954483 天前
CTF 伪协议
php
BingoGo5 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php
JaguarJack5 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php·服务端
BingoGo6 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php