2488 字
12 分钟

Java网络编程详解

2026-02-05
浏览量 加载中...

Java网络编程详解#

什么是网络编程?#

网络编程是指编写程序使不同计算机之间能够进行通信的过程。Java提供了丰富的网络编程API,使得开发者可以方便地实现网络通信功能。

网络编程的基本概念#

1. IP地址#

IP地址是网络中设备的唯一标识,分为IPv4和IPv6两种格式:

  • IPv4:32位地址,格式为点分十进制,如192.168.1.1
  • IPv6:128位地址,格式为冒分十六进制,如2001:0db8:85a3:0000:0000:8a2e:0370:7334

2. 端口号#

端口号是应用程序在设备上的唯一标识,范围为0-65535:

  • 0-1023:系统保留端口
  • 1024-49151:注册端口
  • 49152-65535:动态端口

3. 协议#

协议是通信双方约定的规则,常用的网络协议包括:

  • TCP:传输控制协议,面向连接,可靠传输
  • UDP:用户数据报协议,无连接,不可靠传输
  • HTTP:超文本传输协议,基于TCP
  • HTTPS:安全的HTTP,基于SSL/TLS

4. 套接字(Socket)#

套接字是网络通信的端点,由IP地址和端口号组成。

Java网络编程的核心类#

1. InetAddress#

InetAddress类用于表示IP地址。

import java.net.InetAddress;
import java.net.UnknownHostException;
public class InetAddressDemo {
public static void main(String[] args) {
try {
// 获取本地主机的IP地址
InetAddress localHost = InetAddress.getLocalHost();
System.out.println("本地主机: " + localHost);
System.out.println("主机名: " + localHost.getHostName());
System.out.println("IP地址: " + localHost.getHostAddress());
// 根据主机名获取IP地址
InetAddress baidu = InetAddress.getByName("www.baidu.com");
System.out.println("百度: " + baidu);
System.out.println("主机名: " + baidu.getHostName());
System.out.println("IP地址: " + baidu.getHostAddress());
// 检查主机是否可达
boolean reachable = baidu.isReachable(5000); // 5秒超时
System.out.println("百度是否可达: " + reachable);
// 获取所有IP地址
InetAddress[] addresses = InetAddress.getAllByName("www.baidu.com");
System.out.println("百度的所有IP地址:");
for (InetAddress address : addresses) {
System.out.println(address);
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}

2. Socket#

Socket类用于实现TCP客户端。

3. ServerSocket#

ServerSocket类用于实现TCP服务器。

4. DatagramSocket#

DatagramSocket类用于实现UDP通信。

5. DatagramPacket#

DatagramPacket类用于表示UDP数据包。

TCP编程#

TCP是一种面向连接的、可靠的、基于字节流的传输层协议。

TCP服务器#

import java.io.*;
import java.net.*;
public class TCPServer {
public static void main(String[] args) {
try {
// 创建ServerSocket,监听8080端口
ServerSocket serverSocket = new ServerSocket(8080);
System.out.println("服务器启动,监听端口8080...");
while (true) {
// 接受客户端连接
Socket socket = serverSocket.accept();
System.out.println("客户端连接: " + socket.getInetAddress().getHostAddress());
// 处理客户端请求
new Thread(new ClientHandler(socket)).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 客户端处理器
private static class ClientHandler implements Runnable {
private Socket socket;
public ClientHandler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try (
// 获取输入流
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
// 获取输出流
PrintWriter out = new PrintWriter(
socket.getOutputStream(), true);
) {
String message;
// 读取客户端消息
while ((message = in.readLine()) != null) {
System.out.println("收到客户端消息: " + message);
// 回复客户端
out.println("服务器已收到: " + message);
// 如果客户端发送"bye",则关闭连接
if ("bye".equals(message)) {
break;
}
}
System.out.println("客户端断开连接");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

TCP客户端#

import java.io.*;
import java.net.*;
public class TCPClient {
public static void main(String[] args) {
try (
// 创建Socket,连接到服务器
Socket socket = new Socket("localhost", 8080);
// 获取输入流
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
// 获取输出流
PrintWriter out = new PrintWriter(
socket.getOutputStream(), true);
// 获取键盘输入
BufferedReader keyboard = new BufferedReader(
new InputStreamReader(System.in));
) {
System.out.println("已连接到服务器");
String message;
// 读取键盘输入并发送给服务器
while ((message = keyboard.readLine()) != null) {
out.println(message);
// 读取服务器回复
String response = in.readLine();
System.out.println("服务器回复: " + response);
// 如果发送"bye",则退出循环
if ("bye".equals(message)) {
break;
}
}
System.out.println("连接已关闭");
} catch (IOException e) {
e.printStackTrace();
}
}
}

UDP编程#

UDP是一种无连接的、不可靠的传输层协议,适用于对实时性要求较高的场景。

UDP服务器#

import java.net.*;
public class UDPServer {
public static void main(String[] args) {
try {
// 创建DatagramSocket,监听8080端口
DatagramSocket socket = new DatagramSocket(8080);
System.out.println("服务器启动,监听端口8080...");
byte[] buffer = new byte[1024];
while (true) {
// 创建DatagramPacket用于接收数据
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
// 接收数据
socket.receive(packet);
// 解析数据
String message = new String(packet.getData(), 0, packet.getLength());
System.out.println("收到客户端消息: " + message);
System.out.println("客户端地址: " + packet.getAddress().getHostAddress());
System.out.println("客户端端口: " + packet.getPort());
// 回复客户端
String response = "服务器已收到: " + message;
byte[] responseData = response.getBytes();
DatagramPacket responsePacket = new DatagramPacket(
responseData, responseData.length,
packet.getAddress(), packet.getPort());
socket.send(responsePacket);
// 如果客户端发送"bye",则退出循环
if ("bye".equals(message)) {
break;
}
}
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}

UDP客户端#

import java.net.*;
import java.io.*;
public class UDPClient {
public static void main(String[] args) {
try {
// 创建DatagramSocket
DatagramSocket socket = new DatagramSocket();
InetAddress serverAddress = InetAddress.getByName("localhost");
int serverPort = 8080;
BufferedReader keyboard = new BufferedReader(
new InputStreamReader(System.in));
String message;
while ((message = keyboard.readLine()) != null) {
// 发送数据
byte[] data = message.getBytes();
DatagramPacket packet = new DatagramPacket(
data, data.length, serverAddress, serverPort);
socket.send(packet);
// 接收回复
byte[] buffer = new byte[1024];
DatagramPacket responsePacket = new DatagramPacket(buffer, buffer.length);
socket.receive(responsePacket);
String response = new String(
responsePacket.getData(), 0, responsePacket.getLength());
System.out.println("服务器回复: " + response);
// 如果发送"bye",则退出循环
if ("bye".equals(message)) {
break;
}
}
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}

URL编程#

URL(Uniform Resource Locator)是统一资源定位符,用于标识网络上的资源。

URL类的使用#

import java.net.*;
import java.io.*;
public class URLDemo {
public static void main(String[] args) {
try {
// 创建URL对象
URL url = new URL("https://www.baidu.com");
// 获取URL的各个部分
System.out.println("协议: " + url.getProtocol());
System.out.println("主机: " + url.getHost());
System.out.println("端口: " + url.getPort());
System.out.println("路径: " + url.getPath());
System.out.println("查询: " + url.getQuery());
System.out.println("文件: " + url.getFile());
System.out.println("引用: " + url.getRef());
// 打开连接并读取数据
URLConnection connection = url.openConnection();
try (BufferedReader in = new BufferedReader(
new InputStreamReader(connection.getInputStream()))) {
String line;
StringBuilder content = new StringBuilder();
while ((line = in.readLine()) != null) {
content.append(line).append("\n");
}
// 打印前1000个字符
System.out.println("内容前1000字符: " + content.substring(0, Math.min(1000, content.length())));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

HTTP客户端#

使用HttpURLConnection#

import java.net.*;
import java.io.*;
public class HttpURLConnectionDemo {
public static void main(String[] args) {
try {
// 创建URL对象
URL url = new URL("https://api.github.com/users/octocat");
// 打开连接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// 设置请求方法
connection.setRequestMethod("GET");
// 设置请求头
connection.setRequestProperty("Accept", "application/json");
// 获取响应码
int responseCode = connection.getResponseCode();
System.out.println("响应码: " + responseCode);
// 读取响应数据
BufferedReader in;
if (responseCode == HttpURLConnection.HTTP_OK) {
in = new BufferedReader(
new InputStreamReader(connection.getInputStream()));
} else {
in = new BufferedReader(
new InputStreamReader(connection.getErrorStream()));
}
String line;
StringBuilder content = new StringBuilder();
while ((line = in.readLine()) != null) {
content.append(line).append("\n");
}
in.close();
// 打印响应内容
System.out.println("响应内容: " + content.toString());
// 关闭连接
connection.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
}

使用HttpClient(Java 11+)#

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class HttpClientDemo {
public static void main(String[] args) {
try {
// 创建HttpClient
HttpClient client = HttpClient.newHttpClient();
// 创建HttpRequest
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.github.com/users/octocat"))
.header("Accept", "application/json")
.build();
// 发送请求并获取响应
HttpResponse<String> response = client.send(
request, HttpResponse.BodyHandlers.ofString());
// 打印响应码和响应内容
System.out.println("响应码: " + response.statusCode());
System.out.println("响应内容: " + response.body());
} catch (Exception e) {
e.printStackTrace();
}
}
}

网络编程的最佳实践#

1. 异常处理#

网络编程中可能会遇到各种异常,如连接超时、IO异常等,应该适当处理这些异常。

2. 资源管理#

网络连接是宝贵的资源,应该使用try-with-resources语句或在finally块中关闭资源。

3. 超时设置#

设置合理的超时时间,避免因网络问题导致程序卡死。

4. 线程安全#

在多线程环境下,应该确保网络操作的线程安全。

5. 缓冲区大小#

设置合理的缓冲区大小,提高IO性能。

6. 编码处理#

处理网络数据时,应该使用正确的字符编码,避免乱码。

7. 安全性#

  • 使用HTTPS替代HTTP,确保数据传输的安全性
  • 验证服务器证书,防止中间人攻击
  • 不要在网络上传输敏感信息,如密码

8. 性能优化#

  • 使用连接池,复用网络连接
  • 压缩数据,减少网络传输量
  • 使用NIO或Netty等高性能框架

常见陷阱#

1. 连接泄漏#

没有正确关闭网络连接,导致连接泄漏。

2. 超时设置不当#

没有设置超时时间,导致程序在网络问题时卡死。

3. 编码问题#

使用了错误的字符编码,导致数据传输出现乱码。

4. 线程安全问题#

在多线程环境下,网络操作没有考虑线程安全,导致数据不一致。

5. 缓冲区溢出#

缓冲区大小设置不当,导致缓冲区溢出。

6. 安全性问题#

没有使用安全的传输协议,导致数据被窃取或篡改。

7. 性能问题#

没有优化网络操作,导致性能下降。

8. 端口占用#

使用了已被占用的端口,导致程序启动失败。

9. IP地址和端口号错误#

使用了错误的IP地址或端口号,导致连接失败。

10. 防火墙问题#

防火墙阻止了网络连接,导致程序无法正常通信。

总结#

Java网络编程是Java编程中的重要部分,它允许程序与网络上的其他设备进行通信。Java提供了丰富的网络编程API,包括TCP、UDP、HTTP等协议的支持。

本文介绍了Java网络编程的基本概念、核心类和常用协议的实现方式,以及网络编程的最佳实践和常见陷阱。希望本文能够帮助你更好地理解和使用Java的网络编程。

练习#

  1. 编写一个TCP服务器和客户端,实现简单的聊天功能。

  2. 编写一个UDP服务器和客户端,实现简单的消息传递功能。

  3. 编写一个程序,使用URL类读取网页内容。

  4. 编写一个程序,使用HttpURLConnection发送HTTP请求并处理响应。

  5. 编写一个程序,使用HttpClient(Java 11+)发送HTTP请求并处理响应。

  6. 编写一个程序,实现简单的HTTP服务器。

  7. 编写一个程序,使用InetAddress类获取主机的IP地址。

  8. 编写一个程序,测试网络连接的可达性。

  9. 编写一个程序,实现简单的端口扫描功能。

  10. 编写一个程序,使用NIO实现高性能的网络服务器。

通过这些练习,你将更加熟悉Java的网络编程,为后续的学习做好准备。

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或赞助支持!

赞助
Java网络编程详解
https://blog.vanilla.net.cn/posts/2026-02-05-java-network-programming/
作者
鹁鸪
发布于
2026-02-05
许可协议
CC BY-NC-SA 4.0

评论区

目录