四十二、网络编程(上)——IP、端口与 UDP 编程

想让两台电脑互相传数据?想自己写个聊天工具?

网络编程听起来高大上,其实核心就三件事:IP 地址 + 端口号 + 协议 !📡

上篇先把网络基础和 UDP 协议吃透,手写聊天程序、广播和组播!


一、网络编程三要素 🔑

1.1 计算机网络是什么

实现不同地理位置、不同主机之间的数据交流,让多台计算机形成一个互联的系统。

1.2 核心三要素

复制代码
地址(IP)        → 定位哪台电脑 📍
   ↓
端口号(Port)   → 定位哪个程序 🚪
   ↓
协议(Protocol) → 双方遵守的通信规则 📜
要素 作用 示例
IP 地址 📍 唯一标识一台主机 192.168.1.100
端口号 🚪 标识主机上的应用程序 8080 / 3306
协议 📜 规定数据格式和传输规则 TCP / UDP

二、IP 地址------主机的「身份证」📍

2.1 IPv4 vs IPv6 对比

对比项 IPv4 IPv6
格式 4组十进制(0~255) 8组十六进制(每组4位)
示例 192.168.1.100 2001:0db8:85a3::8a2e:0370:7334
长度 32位(约43亿个) 128位(沙子都能分到IP!)
现状 已经不够用了 ⚠️ 未来主流 ✅

2.2 IPv4 地址规则

复制代码
格式:A.B.C.D(每组0~255)

前三个数字:子网编号(同一局域网)
最后一个数字:主机编号(同一子网内唯一)

特殊地址:
  🏠 127.0.0.1 → 本机回环地址(localhost)
  📡 255.255.255.255 → 广播地址
  🏠 0 → 当前子网编号

2.3 InetAddress 类------Java 中的 IP 对象 📖

核心概念InetAddressjava.net 包中,没有公共构造方法,通过静态方法获取对象。

方法 功能
getLocalHost() 获取本机 IP 对象
getByName(String host) 根据主机名或 IP 字符串获取
getHostName() 获取主机名
getHostAddress() 获取 IP 地址字符串
java 复制代码
import java.net.InetAddress;

public class Demo01 {
    public static void main(String[] args) throws Exception {
        // 1. 获取本机 IP 对象
        InetAddress local = InetAddress.getLocalHost();
        System.out.println("本机主机名:" + local.getHostName());
        System.out.println("本机IP:" + local.getHostAddress());

        // 2. 根据主机名获取(局域网内)
        InetAddress remote = InetAddress.getByName("YR190814-KJQI");
        System.out.println("远程主机:" + remote);

        // 3. 根据 IP 地址获取
        InetAddress byIp = InetAddress.getByName("192.168.26.23");
        System.out.println("根据IP获取:" + byIp);

        // 4. DNS 解析:根据域名获取 IP
        InetAddress baidu = InetAddress.getByName("www.baidu.com");
        System.out.println("百度:" + baidu);
    }
}

💡 命令行:ipconfig -all 查看本机所有 IP 配置!


三、端口号------程序的「门牌号」🚪

3.1 端口号规则

  • 范围0 ~ 65535(2个字节,2^16)
  • 0~1023:系统保留端口,不建议使用 ⚠️
  • 1024~49151:注册端口,可以自定义使用 ✅
  • 49152~65535:动态端口,系统临时分配

3.2 常见默认端口

程序 端口号 说明
HTTP 80 默认不写端口就是 80
HTTPS 443 加密 HTTP
MySQL 3306 数据库默认端口
Tomcat 8080 Java Web 服务器
Oracle 1521 Oracle 数据库

3.3 ⚠️ 端口冲突

复制代码
同一台电脑上,两个程序不能使用同一个端口!
程序A 用了 8888 → 程序B 再用 8888 → 报错:端口已被占用!

解决:换端口号或关闭占用程序。


四、协议------通信的「交通规则」📜

4.1 TCP/IP 协议簇

复制代码
应用层    HTTP、HTTPS、FTP     ← 我们主要学这里 📋
  ↓
传输层    TCP、UDP            ← 两种传输协议
  ↓
网络层    IP、ICMP
  ↓
物理层    网线、光纤、WiFi     ← 硬件设备

4.2 UDP vs TCP 核心对比 💼

对比项 UDP TCP
连接性 无连接 ❌ 面向连接 ✅
可靠性 不可靠(可能丢包) 可靠(确认机制)✅
效率 高 ✅
类比 发短信、寄信 📮 打电话 ☎️
场景 视频流、DNS、广播 网页、文件下载、聊天
Java 类 DatagramSocket Socket / ServerSocket

五、UDP 编程------无连接的「快递员」📮

5.1 UDP 特点

  • 无连接:发送前不用确认接收端是否准备好
  • 不可靠:可能丢包,不保证送达
  • 效率高:没有握手和确认开销
  • 两端平等 :发送端和接收端都是 DatagramSocket

5.2 核心类

类名 作用
DatagramSocket UDP 套接字,既能发也能收
DatagramPacket 数据包,封装要发送/接收的数据

5.3 DatagramSocket

构造方法 说明
DatagramSocket() 创建发送端,端口随机
DatagramSocket(int port) 创建接收端,指定端口
成员方法 说明
send(DatagramPacket p) 发送数据包
receive(DatagramPacket p) 接收数据包(阻塞)

5.4 DatagramPacket ------ 数据的「快递盒」📦

发送用的构造

java 复制代码
DatagramPacket(byte[] buf, int length, InetAddress address, int port)
// buf:     要发送的数据(字节数组)
// length:  要发送的长度
// address: 目标 IP 地址
// port:    目标端口号

接收用的构造

java 复制代码
DatagramPacket(byte[] buf, int length)
// buf:    接收数据的缓冲区
// length: 接收数据的最大长度

5.5 UDP 发送端代码

java 复制代码
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class UDP_Sender {
    public static void main(String[] args) throws Exception {
        // 1. 创建发送端套接字(端口随机)
        DatagramSocket ds = new DatagramSocket();

        // 2. 准备要发送的数据
        String msg = "江总,开房啊!";
        byte[] data = msg.getBytes();

        // 3. 封装数据包(指定目标地址+端口)
        DatagramPacket dp = new DatagramPacket(
            data, data.length,
            InetAddress.getByName("192.168.26.23"), 6666
        );

        // 4. 发送数据
        ds.send(dp);
        System.out.println("发送完成!📮");

        // 5. 关闭资源
        ds.close();
    }
}

5.6 UDP 接收端代码

java 复制代码
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class UDP_Receiver {
    public static void main(String[] args) throws Exception {
        System.out.println("接收端启动,等待数据...📩");

        // 1. 创建接收端套接字,指定监听端口
        DatagramSocket ds = new DatagramSocket(6666);

        // 2. 准备接收缓冲区
        byte[] buf = new byte[1024];
        DatagramPacket dp = new DatagramPacket(buf, buf.length);

        // 3. 接收数据(阻塞,直到收到数据)
        ds.receive(dp);

        // 4. 解析数据
        String msg = new String(dp.getData(), 0, dp.getLength());
        System.out.println("收到消息:" + msg);

        // 5. 关闭
        ds.close();
    }
}

5.7 ⚠️ UDP 注意点

  1. 接收端必须先启动!虽然无连接,但没人监听就丢包了
  2. receive() 方法阻塞,直到收到数据
  3. 发送端端口随机,接收端端口必须指定
  4. 数据最大长度:65,507 字节

六、UDP 聊天小程序 💬

6.1 发送端(带键盘录入 + 收回复)

java 复制代码
import java.net.*;
import java.util.Scanner;

public class UDP_ChatSender {
    public static void main(String[] args) throws Exception {
        DatagramSocket ds = new DatagramSocket();
        Scanner sc = new Scanner(System.in);

        while (true) {
            System.out.print("请输入(exit退出):");
            String msg = sc.next();

            // 发送消息
            byte[] data = msg.getBytes();
            DatagramPacket dp = new DatagramPacket(
                data, data.length,
                InetAddress.getLocalHost(), 9000
            );
            ds.send(dp);

            if ("exit".equalsIgnoreCase(msg)) {
                System.out.println("发送端退出!👋");
                break;
            }

            // 接收对方回复
            byte[] buf = new byte[1024];
            dp = new DatagramPacket(buf, buf.length);
            ds.receive(dp);
            System.out.println("对方回复:" + new String(buf, 0, dp.getLength()));
        }
        ds.close();
    }
}

6.2 接收端(收消息 + 回复)

java 复制代码
import java.net.*;
import java.util.Scanner;

public class UDP_ChatReceiver {
    public static void main(String[] args) throws Exception {
        DatagramSocket ds = new DatagramSocket(9000);
        Scanner sc = new Scanner(System.in);
        System.out.println("接收端启动,等待聊天...💬");

        while (true) {
            // 接收消息
            byte[] buf = new byte[1024];
            DatagramPacket dp = new DatagramPacket(buf, buf.length);
            ds.receive(dp);
            String msg = new String(buf, 0, dp.getLength());
            System.out.println("收到:" + msg);

            if ("exit".equalsIgnoreCase(msg)) {
                System.out.println("接收端退出!👋");
                break;
            }

            // 回复消息
            System.out.print("请输入回复:");
            String reply = sc.next();
            byte[] replyData = reply.getBytes();
            DatagramPacket replyPacket = new DatagramPacket(
                replyData, replyData.length,
                dp.getAddress(), dp.getPort()  // 从收到的包中获取发送方地址
            );
            ds.send(replyPacket);
        }
        ds.close();
    }
}

七、UDP 广播 📡

7.1 什么是广播

向子网内所有主机 发送数据,广播地址必须是 255.255.255.255

7.2 广播发送端

java 复制代码
import java.net.*;

public class UDP_BroadcastSender {
    public static void main(String[] args) throws Exception {
        String msg = "江总真帅!";
        byte[] data = msg.getBytes();

        // ⚠️ 广播地址:255.255.255.255
        DatagramPacket dp = new DatagramPacket(
            data, data.length,
            InetAddress.getByName("255.255.255.255"), 9999
        );

        DatagramSocket ds = new DatagramSocket();
        ds.send(dp);
        ds.close();
        System.out.println("广播发送完成!📡");
    }
}

7.3 广播接收端

java 复制代码
import java.net.*;

public class UDP_BroadcastReceiver {
    public static void main(String[] args) throws Exception {
        DatagramSocket ds = new DatagramSocket(9999);
        byte[] buf = new byte[1024];
        DatagramPacket dp = new DatagramPacket(buf, buf.length);

        ds.receive(dp);
        System.out.println("收到广播:" + new String(buf, 0, dp.getLength()));
        ds.close();
    }
}

八、UDP 组播 📡

8.1 什么是组播

特定组 的主机发送数据,只有加入该组的成员才能收到(订阅模式)。

组播地址范围224.0.0.0 ~ 239.255.255.255

8.2 组播发送端

java 复制代码
import java.net.*;

public class UDP_MulticastSender {
    public static void main(String[] args) throws Exception {
        String msg = "天成,也很帅!";
        byte[] data = msg.getBytes();

        // 组播地址(必须在 224.0.0.0 ~ 239.255.255.255)
        DatagramPacket dp = new DatagramPacket(
            data, data.length,
            InetAddress.getByName("225.0.0.10"), 8888
        );

        // 发送端用 MulticastSocket(和普通 UDP 一样)
        MulticastSocket ms = new MulticastSocket();
        ms.send(dp);
        ms.close();
        System.out.println("组播发送完成!📡");
    }
}

8.3 组播接收端(需加入组)

java 复制代码
import java.net.*;

public class UDP_MulticastReceiver {
    public static void main(String[] args) throws Exception {
        MulticastSocket ms = new MulticastSocket(8888);

        // ⚠️ 关键:加入组播组!
        InetAddress group = InetAddress.getByName("225.0.0.10");
        ms.joinGroup(group);

        // 接收数据
        byte[] buf = new byte[1024];
        DatagramPacket dp = new DatagramPacket(buf, buf.length);
        ms.receive(dp);
        System.out.println("收到组播:" + new String(buf, 0, dp.getLength()));

        ms.close();
    }
}

8.4 💡 广播 vs 组播

对比项 广播 组播
地址 255.255.255.255 224.0.0.0 ~ 239.255.255.255
接收者 子网内所有主机 只有加入组的成员
Java 类 DatagramSocket MulticastSocket
类比 大喇叭喊话 📢 微信群发消息 📱

本篇总结 📝

  1. 网络三要素 🔑:IP 地址(定位主机)+ 端口号(定位程序)+ 协议(通信规则)
  2. IP 地址 📍:IPv4(43亿个)vs IPv6(沙子都能分到),InetAddress 类获取
  3. 端口号 🚪:0~65535,1024+ 可自定义,常见端口要记(80/3306/8080)
  4. UDP 协议 📮:无连接、不可靠、效率高,DatagramSocket + DatagramPacket
  5. UDP 编程 📮:发送端端口随机、接收端端口固定、receive() 阻塞
  6. UDP 聊天 💬:死循环 + 键盘录入 + receive 收回复
  7. 广播 📡:地址 255.255.255.255,子网内所有主机都能收到
  8. 组播 📡:地址 224.x.x.x,需要 joinGroup() 加入组才能收到

🚀 下一篇预告:《四十三、网络编程(下)------TCP 编程与 HTTP 入门》------ 三次握手、文件上传、多线程并发服务器,理解网页背后的 HTTP 原理!


作者 :书源丶
发布平台:CSDN

相关推荐
m0_710890871 小时前
2026 年进销存系统大盘点:国内外 5 款主流进销存软件对比与选型指南
java·数据库·mysql
devilnumber1 小时前
maven依赖的直接下载jar
java·maven
人道领域1 小时前
【LeetCode刷题日记】二叉树层序遍历完全指南:从基础到LeetCode实战一篇搞定BFS模板,秒杀4道经典面试题
java·开发语言·数据结构·leetcode·面试·二叉树
承渊政道1 小时前
CentOS 7部署Elasticsearch完整流程:避坑、基础操作、远程访问
java·linux·elasticsearch·系统架构·centos·远程工作·持续部署
德迅云安全-小潘2 小时前
App被恶意攻击了怎么办?一份全面的应急响应与防护指南
网络
S1998_1997111609•X2 小时前
论述情况盀导致系统应用通信通讯协议被恶意注入污染蜜罐开元盀用于非法侵入爬虫植入ssd的通用技术原理
网络·网络协议·百度·哈希算法·开闭原则
咖啡八杯2 小时前
GoF设计模式——工厂方法模式
java·后端·设计模式
代码羊羊3 小时前
Rust 迭代器完全通俗易懂指南(零基础全覆盖)
java·开发语言·rust
MY_TEUCK10 小时前
【Java 后端】SpringBoot 登录认证与会话跟踪实战(JWT + Filter/Interceptor)
java·开发语言·spring boot