在这里插## 标题入图片描述

> 						大家好,我是程序员小羊!

✨博客主页: https://blog.csdn.net/m0_63815035?type=blog

💗《博客内容》:大数据、AI开发、Java、测试开发、Python、Android、Go、Node、Android前端小程序等相关领域知识
📢博客专栏: https://blog.csdn.net/m0_63815035/category_11954877.html
📢欢迎点赞 👍 收藏 ⭐留言 📝
📢本文为学习笔记资料,如有侵权,请联系我删除,疏漏之处还请指正🙉
📢大厦之成,非一木之材也;大海之阔,非一流之归也✨

在这里插入图片描述

网络编程是 Java 高级开发的重要部分,用于实现跨主机的数据交换。本文从网络基础概念讲起,详细介绍 InetAddress、URL、UDP 和 TCP 编程,并提供完整的服务端/客户端代码示例,覆盖常见注意事项和最佳实践。


一、计算机网络基础

在这里插入图片描述

1.1 什么是计算机网络

计算机网络是将分布在不同地理区域的计算机与外部设备通过通信线路互连,形成一个规模大、功能强的网络系统,使众多计算机可以方便地传递信息,共享硬件、软件、数据等资源。

主要功能

  • 资源共享
  • 信息传输与集中处理
  • 均衡负荷与分布处理

1.2 网络通信协议

通信协议是计算机网络中实现通信必须遵守的规则和约定,包括:速率、传输代码、代码结构、传输控制步骤、出错控制等。

协议三要素:

  • 语义:做什么(如控制信息、差错处理)
  • 语法:怎么做(数据结构、格式)
  • 时序:做的顺序(速度匹配、排序)

1.3 网络分层模型

OSI 七层模型(理论模型)
层级 名称 作用
7 应用层 提供用户接口(HTTP、FTP、SMTP)
6 表示层 数据转换、加密、压缩
5 会话层 建立、管理、终止会话
4 传输层 端到端可靠传输(TCP、UDP)
3 网络层 路由选择、IP 地址
2 数据链路层 帧传输、差错控制
1 物理层 比特流传输、硬件接口

在这里插入图片描述

TCP/IP 四层模型(实际应用)
层级 名称 协议示例
4 应用层 HTTP、FTP、DNS、SMTP
3 传输层 TCP、UDP
2 网际层 IP、ICMP、ARP
1 网络接口层 以太网、WiFi

在这里插入图片描述

1.4 数据封装与拆封

  • 封装:发送数据时,从应用层向下传递,每层加上本层的头部(可能尾部),形成数据包。
    在这里插入图片描述

  • 拆封:接收数据时,从物理层向上传递,每层去掉本层的头部,还原原始数据。
    在这里插入图片描述

理解封装与拆封,有助于理解网络编程中“流”的概念。


二、IP 地址与端口

2.1 IP 地址

IP 地址用于唯一标识网络中的计算机(或网络设备)。IPv4 地址为 32 位整数,通常用点分十进制表示(如 192.168.1.1)。IPv6 为 128 位,用冒号十六进制表示。

特殊 IP

  • 127.0.0.1:本地回环地址,代表本机。
  • localhost:本地主机域名,默认映射到 127.0.0.1

2.2 端口

端口是虚拟概念,用于区分同一主机上的不同网络应用程序。端口号范围 0~65535

  • 0~1023:系统保留端口(如 HTTP 80,FTP 21,SSH 22)
  • 1024~49151:注册端口(用户程序可使用)
  • 49152~65535:动态/私有端口

注意:编写程序时,建议使用 1024 以上的端口,避免冲突。

2.3 InetAddress 类(Java 中表示 IP 地址)

java.net.InetAddress 用于封装 IP 地址和域名,不包含端口信息。该类没有公共构造方法,通过静态方法获取实例。

常用静态方法

方法 说明
InetAddress.getLocalHost() 获取本机 InetAddress 对象
InetAddress.getByName(String host) 根据域名或 IP 字符串获取
InetAddress.getAllByName(String host) 获取域名对应的所有 IP(适用于多 IP 主机)

实例方法

方法 说明
String getHostAddress() 返回 IP 地址字符串
String getHostName() 返回域名(若无法解析则返回 IP)
boolean isReachable(int timeout) 测试是否可达(ICMP ping)

示例

import java.net.InetAddress;

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

        // 根据域名获取
        InetAddress baidu = InetAddress.getByName("www.baidu.com");
        System.out.println("百度IP:" + baidu.getHostAddress());
        System.out.println("百度域名:" + baidu.getHostName());

        // 根据 IP 获取(可能无法反向解析域名)
        InetAddress byIp = InetAddress.getByName("8.8.8.8");
        System.out.println("8.8.8.8 主机名:" + byIp.getHostName()); // 可能仍返回 IP
    }
}

2.4 InetSocketAddress 类(IP + 端口)

java.net.InetSocketAddress 包含 IP 地址(或主机名)和端口号,常用于 Socket 通信中指定远程端点。

构造方法

  • InetSocketAddress(String hostname, int port)
  • InetSocketAddress(InetAddress addr, int port)
  • InetSocketAddress(int port):创建只包含端口的通配地址(用于服务器)

常用方法

  • InetAddress getAddress()
  • int getPort()
  • String getHostName()
InetSocketAddress endpoint = new InetSocketAddress("localhost", 8888);
System.out.println("主机名:" + endpoint.getHostName());
System.out.println("端口:" + endpoint.getPort());
System.out.println("IP:" + endpoint.getAddress().getHostAddress());

三、URL 与网络资源访问

3.1 URL 简介

URL(Uniform Resource Locator)统一资源定位符,用于标识互联网上资源的位置。格式:

protocol://userInfo@host:port/path?query#fragment
  • protocol:协议(http, https, ftp, file 等)
  • host:域名或 IP
  • port:端口(可省略,使用协议默认端口)
  • path:资源路径
  • query:查询参数(如 ?id=1&name=xx
  • fragment:锚点(定位到页面内某位置)

3.2 URL 类(java.net.URL)

构造方法

  • URL(String spec):完整 URL 字符串
  • URL(String protocol, String host, int port, String file)
  • URL(URL context, String spec):相对路径构造

常用方法

  • String getProtocol():获取协议名
  • String getHost():获取主机名
  • int getPort():获取端口(若未指定返回 -1)
  • String getPath():获取路径
  • String getQuery():获取查询参数
  • InputStream openStream():打开到此 URL 的连接并返回输入流(用于读取资源)

3.3 网络爬虫雏形(下载网页)

import java.io.*;
import java.net.URL;

public class URLDownload {
    public static void main(String[] args) throws Exception {
        URL url = new URL("https://www.baidu.com");
        // 使用 try-with-resources 自动关闭流
        try (InputStream is = url.openStream();
             BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
             BufferedWriter writer = new BufferedWriter(new FileWriter("baidu.html"))) {
            String line;
            while ((line = reader.readLine()) != null) {
                writer.write(line);
                writer.newLine();
            }
        }
        System.out.println("下载完成");
    }
}

注意:实际网络爬虫需要考虑:User-Agent 伪装、请求延迟、异常处理、编码识别等,本示例仅供学习原理。


四、传输层协议:TCP 与 UDP

特性 TCP UDP
连接性 面向连接(三次握手) 无连接
可靠性 可靠、确认重传 不可靠,可能丢包
有序性 保证顺序 不保证顺序
流量控制
开销 大(头部 20 字节) 小(头部 8 字节)
速度
应用场景 HTTP、FTP、SSH、数据库 视频直播、DNS、VoIP

比喻:TCP 像打电话(先拨号建立连接,再通话,挂断),UDP 像寄信(不管对方是否收到,直接发送)。


五、UDP 编程(DatagramSocket + DatagramPacket)

UDP 使用 DatagramSocket 发送/接收 DatagramPacket 数据报。
在这里插入图片描述

5.1 DatagramSocket

  • 用于发送或接收数据报的套接字。
  • 构造方法:
    • DatagramSocket():系统随机分配本地端口(客户端常用)
    • DatagramSocket(int port):绑定到指定端口(服务端常用)
    • DatagramSocket(int port, InetAddress bindAddr):绑定到特定网卡
  • 常用方法:
    • void send(DatagramPacket p)
    • void receive(DatagramPacket p) (阻塞)
    • void close()

5.2 DatagramPacket

  • 数据报容器,包含数据、长度、目标地址和端口。
  • 构造方法(发送用):
    • DatagramPacket(byte[] buf, int length, InetAddress address, int port)
    • DatagramPacket(byte[] buf, int length, SocketAddress address)
  • 构造方法(接收用):
    • DatagramPacket(byte[] buf, int length)
  • 常用方法:
    • byte[] getData()
    • int getLength()
    • InetAddress getAddress()
    • int getPort()

5.3 UDP 服务端示例

import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class UDPServer {
    public static void main(String[] args) throws Exception {
        // 1. 创建服务端 DatagramSocket,监听端口 8888
        try (DatagramSocket ds = new DatagramSocket(8888)) {
            byte[] buf = new byte[1024];
            DatagramPacket dp = new DatagramPacket(buf, buf.length);
            System.out.println("UDP 服务端已启动,等待数据...");
            ds.receive(dp); // 阻塞,直到收到数据报
            String received = new String(dp.getData(), 0, dp.getLength());
            System.out.println("收到客户端消息:" + received);
            System.out.println("客户端地址:" + dp.getAddress().getHostAddress() + ":" + dp.getPort());
        }
    }
}

5.4 UDP 客户端示例

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;

public class UDPClient {
    public static void main(String[] args) throws Exception {
        // 1. 创建客户端 DatagramSocket(系统自动分配端口)
        try (DatagramSocket ds = new DatagramSocket()) {
            String msg = "Hello UDP Server";
            byte[] buf = msg.getBytes("UTF-8");
            // 封装数据包,指定目标地址和端口
            DatagramPacket dp = new DatagramPacket(buf, buf.length,
                    new InetSocketAddress("localhost", 8888));
            ds.send(dp);
            System.out.println("数据已发送");
        }
    }
}

注意:UDP 是不可靠的,如果服务端未启动,客户端发送不会报错,但数据会丢失。如果需要确认,可以设计应用层确认机制。


六、TCP 编程(ServerSocket + Socket)

TCP 通信需要服务端 ServerSocket 监听端口,客户端 Socket 发起连接,建立后通过 Socket 的输入输出流进行双向通信。

6.1 ServerSocket(服务端)

  • 构造方法:
    • ServerSocket(int port):绑定到端口,默认最大等待队列长度 50
    • ServerSocket(int port, int backlog):指定队列长度
    • ServerSocket(int port, int backlog, InetAddress bindAddr):绑定到指定网卡
  • 常用方法:
    • Socket accept():阻塞等待客户端连接,返回 Socket 对象
    • void close()

6.2 Socket(客户端/服务端通信端点)

  • 客户端构造方法:
    • Socket(String host, int port):连接指定主机和端口
    • Socket(InetAddress address, int port)
  • 服务端通过 accept() 返回的 Socket
  • 常用方法:
    • InputStream getInputStream()
    • OutputStream getOutputStream()
    • void close()
    • InetAddress getInetAddress()
    • int getPort()

6.3 TCP 服务端示例(接收客户端消息并回复)

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPServer {
    public static void main(String[] args) {
        try (ServerSocket server = new ServerSocket(8888)) {
            System.out.println("TCP 服务端已启动,等待连接...");
            Socket socket = server.accept(); // 阻塞
            System.out.println("客户端已连接:" + socket.getInetAddress().getHostAddress());

            // 接收客户端数据
            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String line = reader.readLine();
            System.out.println("收到客户端消息:" + line);

            // 向客户端发送响应
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            writer.write("已收到消息:" + line);
            writer.newLine();
            writer.flush();

            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

6.4 TCP 客户端示例

import java.io.*;
import java.net.Socket;

public class TCPClient {
    public static void main(String[] args) {
        try (Socket socket = new Socket("localhost", 8888)) {
            // 发送数据
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            writer.write("Hello TCP Server");
            writer.newLine();
            writer.flush();

            // 接收响应
            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String response = reader.readLine();
            System.out.println("服务端响应:" + response);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

6.5 多线程 TCP 服务端(支持多个客户端同时连接)

实际开发中,服务端需要同时处理多个客户端,应为每个客户端分配独立线程。

public class MultiThreadTCPServer {
    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(8888);
        System.out.println("服务端启动,等待客户端...");
        while (true) {
            Socket socket = server.accept();
            // 每个客户端交给一个线程处理
            new Thread(new ClientHandler(socket)).start();
        }
    }

    static class ClientHandler implements Runnable {
        private Socket socket;
        ClientHandler(Socket s) { socket = s; }
        @Override
        public void run() {
            try (socket) {
                BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
                String line;
                while ((line = reader.readLine()) != null) {
                    System.out.println("收到:" + line);
                    writer.write("Echo: " + line);
                    writer.newLine();
                    writer.flush();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

注意:实际项目中常使用线程池管理线程,避免无限制创建线程导致资源耗尽。


七、TCP 三次握手与四次挥手(简单理解)

  • 三次握手(建立连接):

    1. Client → Server:SYN(请求连接)
    2. Server → Client:SYN+ACK(同意连接)
    3. Client → Server:ACK(确认连接建立)
  • 四次挥手(断开连接):

    1. Client → Server:FIN(请求断开)
    2. Server → Client:ACK(确认收到)
    3. Server → Client:FIN(关闭服务端到客户端连接)
    4. Client → Server:ACK(确认关闭)

八、常见问题与最佳实践

8.1 常见异常及处理

异常 可能原因 解决方法
BindException 端口已被占用 更换端口,或关闭占用进程
ConnectException 连接被拒绝(服务端未启动) 确保服务端已运行
SocketTimeoutException 读写超时 设置 setSoTimeout 或检查网络
SocketException: Socket closed 在关闭后读写 检查代码逻辑,避免使用已关闭的流
UnknownHostException 主机名无法解析 检查 DNS 或 IP 是否正确

8.2 性能与资源管理

  • 使用 try-with-resources 自动关闭 Socket 和流(Java 7+)。
  • 服务端使用线程池处理并发请求,避免 new Thread() 无限制。
  • 设置合理的 SO_TIMEOUT 防止 accept 或 read 无限阻塞。
  • 对于长连接,建议设置 SO_KEEPALIVE 或应用层心跳。

8.3 数据编码

  • 网络传输建议统一使用 UTF-8 编码,避免乱码。
  • 使用 InputStreamReader / OutputStreamWriter 并指定字符集。

8.4 协议选择

  • 需要可靠传输、顺序保证、数据完整性 → TCP
  • 实时性要求高、允许少量丢包 → UDP

九、结尾

核心类 作用 常用方法
InetAddress 封装 IP/域名 getByName, getHostAddress
InetSocketAddress IP + 端口 getAddress, getPort
URL 资源定位 openStream
DatagramSocket UDP 套接字 send, receive, close
DatagramPacket UDP 数据报 构造、getData
ServerSocket TCP 服务端监听 accept
Socket TCP 双向通信 getInputStream, getOutputStream

掌握网络编程需要理解 TCP/UDP 协议区别,熟悉 Java 提供的 Socket API,并能处理多线程、资源关闭、异常等实际问题。建议多动手编写聊天室、文件传输等小项目加深理解。

今天这篇文章就到这里了,大厦之成,非一木之材也;大海之阔,非一流之归也。感谢大家观看本文

在这里插入图片描述

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐