Java | 网络编程
更新: 2/2/2025 字数: 0 字 时长: 0 分钟
TCP 和 UDP
TCP(传输控制协议)
- 面向连接:通信前需通过三次握手建立可靠连接,形成数据传输通道。
- 可靠传输:数据按序到达、无丢失、无重复,通过确认机制和重传策略保证可靠性。
- 通信模型:基于客户端-服务端架构,需明确区分发送方与接收方角色。
- 大数据量支持:支持高带宽应用(如文件传输、网页浏览),无单次传输大小限制。
- 连接释放:传输结束后通过四次挥手断开连接,额外开销降低实时性,效率较低。
UDP(用户数据包协议)
- 无连接:直接发送封装好的数据包(含源/目的地址和端口),无需预先建立连接。
- 传输限制:单次数据包大小不超过 64KB(受协议头限制),不适合流式大数据传输。
- 不可靠性:不保证数据顺序、完整性,可能丢失或重复,无重传机制。
- 高效性:无需连接建立/释放过程,资源占用少,延迟低,适合实时应用(如视频通话、在线游戏)。
对比
特性 TCP UDP 连接方式 面向连接(三次握手/四次挥手) 无连接 可靠性 可靠传输,数据有序、无丢失 不可靠,可能丢包、乱序 数据量 支持大数据流传输 单次≤64KB,适合小数据包 效率 延迟高,占用资源多 延迟低,资源占用少 典型应用 网页浏览(HTTP)、邮件(SMTP) 视频流(VoIP)、DNS查询 注意
- UDP 端口和 TCP 端口虽然都使用
0~65535
,但他们是两套独立的端口。 - 即一个应用程序用 TCP 占用了端口
1234
,不影响另一个应用程序用 UDP 占用端口1234
。
- UDP 端口和 TCP 端口虽然都使用
InetAddress 类
常用方法
方法 描述 static InetAddress getLocalHost()
获取表示本机地址的 InetAddress
对象,可能包含主机名和 IP 地址static InetAddress getByName(String host)
根据主机名或域名解析对应的 IP 地址,返回 InetAddress
对象String getHostName()
获取 InetAddress
对象关联的主机名,若无法解析则返回 IP 地址字符串String getHostAddress()
获取 InetAddress
对象关联的 IP 地址字符串
TCP 编程
基本介绍
- TCP 编程需要创建客户端和服务端程序,分别通过
Socket
和ServerSocket
进行通信。
- TCP 编程需要创建客户端和服务端程序,分别通过
使用
- 服务端:需要创建一个
ServerSocket
对象,绑定到指定的端口,并通过accept()
方法等待客户端的连接请求。 - 客户端:通过
Socket
连接服务端,然后发送和接收数据。
点击查看案例演示
javaimport java.io.*; import java.net.*; public class TCPServer { public static void main(String[] args) { try { // 创建服务端套接字,绑定到指定端口 ServerSocket serverSocket = new ServerSocket(12345); System.out.println("服务端启动,等待连接..."); // 接受客户端连接 Socket socket = serverSocket.accept(); System.out.println("客户端已连接"); // 获取客户端输入流 InputStream input = socket.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(input)); String message = reader.readLine(); System.out.println("收到客户端消息:" + message); // 向客户端发送响应 OutputStream output = socket.getOutputStream(); PrintWriter writer = new PrintWriter(output, true); writer.println("欢迎来到服务端"); // 关闭资源 socket.close(); serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } }
javaimport java.io.*; import java.net.*; public class TCPClient { public static void main(String[] args) { try { // 连接到服务端(指定 IP 和端口) Socket socket = new Socket("localhost", 12345); // 向服务端发送消息 OutputStream output = socket.getOutputStream(); PrintWriter writer = new PrintWriter(output, true); writer.println("你好,服务端!"); // 接收服务端的响应 InputStream input = socket.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(input)); String response = reader.readLine(); System.out.println("服务端响应:" + response); // 关闭资源 socket.close(); } catch (IOException e) { e.printStackTrace(); } } }
text服务端启动,等待连接... 客户端已连接 收到客户端消息:你好,服务端! 进程已结束,退出代码为 0
text服务端响应:欢迎来到服务端 进程已结束,退出代码为 0
- 服务端:需要创建一个
Socket 类
基本概念
- 任意两台设备间的通信,均需通过各自的 Socket 作为数据传输的起点与终点。
- 网络通信的本质是两个 Socket 之间的交互,通过 IP 地址和端口号精准定位通信对象。
- Socket 允许程序把网络连接当成一个流,数据在两个 Socket 间通过 IO 传输。
- 一般主动发起通信的应用程序属客户端,等待通信请求的为服务端。
构造方法
构造方法 描述 Socket(String host, int port)
直接连接到指定主机名/IP 字符串的指定端口 Socket(InetAddress address, int port)
连接到已知 IP 对象的指定端口(避免重复解析主机名) Socket(String host, int port, InetAddress localAddr, int localPort)
绑定本地地址和端口,再连接远程主机(适用于多网卡环境) Socket(InetAddress address, int port, InetAddress localAddr, int localPort)
同上,但远程地址直接使用 InetAddress 对象 Socket()
创建未连接的 Socket 对象,需后续调用 connect()
方法常用方法
方法 描述 InputStream getInputStream()
返回此套接字的输入流 OutputStream getOutputStream()
返回此套接字的输出流
ServerSocket 类
构造方法
构造方法 描述 ServerSocket(int port)
创建绑定到指定端口的服务端套接字 常用方法
方法 描述 Socket accept()
侦听对此套接字的连接并接受它,该方法将阻塞,直到建立连接
UDP 编程
基本介绍
- UDP 编程通过
DatagramSocket
和DatagramPacket
进行通信,数据是以数据包形式发送的,无需建立连接。 DatagramPacket
类将数据封装成数据包。DatagramSocket
类用于发送和接收数据包。
- UDP 编程通过
使用
- 服务端:通过
DatagramSocket
监听客户端发送的数据包,并解析接收到的数据。 - 客户端:通过
DatagramSocket
发送数据包到服务端,并接收响应。
点击查看案例演示
javaimport java.io.IOException; import java.net.*; public class UDPServer { public static void main(String[] args) throws IOException { // 创建一个 UDP 套接字并绑定到指定的端口 12345 DatagramSocket socket = new DatagramSocket(12345); byte[] buffer = new byte[1024]; // 创建一个缓存区,用于接收数据 System.out.println("服务端启动,等待数据..."); // 创建一个数据包用于接收客户端的数据 DatagramPacket packet = new DatagramPacket(buffer, buffer.length); socket.receive(packet); // 接收来自客户端的数据报 // 获取接收到的数据的长度和数据,并将其转换为字符串 int length = packet.getLength(); byte[] data = packet.getData(); String message = new String(data, 0, length); // 使用数据的有效长度来创建字符串 System.out.println("收到客户端消息:" + message); // 打印收到的消息 // 创建响应消息并发送给客户端 data = ("服务端已接收到消息:" + message).getBytes(); // 将响应消息转换为字节数组 DatagramPacket responsePacket = new DatagramPacket(data, data.length, packet.getAddress(), packet.getPort()); socket.send(responsePacket); // 发送响应数据报 // 关闭套接字 socket.close(); System.out.println("服务端退出"); } }
javaimport java.io.IOException; import java.net.*; public class UDPClient { public static void main(String[] args) throws IOException { // 创建一个 UDP 套接字 DatagramSocket socket = new DatagramSocket(); // 将客户端发送的消息(中文)转换为字节数组 byte[] data = "你好,服务端!".getBytes(); // 将消息转换为字节数组 DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getByName("localhost"), 12345); socket.send(packet); // 发送数据报到服务端 // 创建一个缓冲区用于接收服务端的响应 byte[] buffer = new byte[1024]; DatagramPacket responsePacket = new DatagramPacket(buffer, buffer.length); socket.receive(responsePacket); // 接收服务端响应的数据报 // 获取响应数据的有效长度,并转换为字符串 int length = responsePacket.getLength(); data = responsePacket.getData(); String response = new String(data, 0, length); // 使用数据的有效长度来创建字符串 System.out.println("收到服务端响应:" + response); // 打印服务端的响应 // 关闭套接字 socket.close(); System.out.println("客户端退出"); } }
text服务端启动,等待数据... 收到客户端消息:你好,服务端! 服务端退出 进程已结束,退出代码为 0
text收到服务端响应:服务端已接收到消息:你好,服务端! 客户端退出 进程已结束,退出代码为 0
- 服务端:通过