Java Socket 编程详解:TCP/UDP 通信与文件上传实战
Java Socket 是进行网络通信的核心 API。本文将深入解析 InetAddress 地址获取方法,分别演示 TCP(面向连接)和 UDP(无连接)的 Socket 编程流程,包括完整的客户端与服务端代码实现,并详细说明如何利用流对象完成文件上传功能,帮助开发者掌握基础网络通信原理与实战技巧。
InetAddress 基础与主机信息获取
在进行 Socket 通信前,通常需要先获取本地或远程主机的 IP 地址及主机名。Java 提供了 InetAddress 类来处理 IP 地址。
1. 获取本地主机信息:
- 方法:使用
InetAddress.getLocalHost()获取本地主机对象。 - 获取 IP:调用
i.getHostAddress()返回 IP 字符串。 - 获取字节数组:调用
i.getAddress()返回 IP 的字节数组表示。
2. 根据主机名获取信息:
- 可以通过
InetAddress.getByName("hostname")指定计算机名称或域名,系统会尝试解析并获取对应的主机信息。例如:InetAddress ibaidu = InetAddress.getByName("www.baidu.com")。
3. URL 中的主机提取:
若已创建 URL 对象,可直接调用 url.getHost() 获取其中的主机名部分。
TCP 协议通信实现
TCP(传输控制协议)是面向连接的、可靠的传输方式。建立 Socket 服务时必须确保服务端存在并连接成功,之后才可在通道内进行数据传输。
第1步:服务端启动与监听 (ServerSocket)
目的:开启服务器端口,等待客户端连接并接收数据。
入口:java.net.ServerSocket
操作顺序:
- 创建服务:实例化
ServerSocket并绑定端口(如 10003)。构造函数支持指定 backlog 参数以限制最大连接数。ServerSocket ss = new ServerSocket(10003); - 等待连接:调用
ss.accept()。此方法为阻塞式,若无客户端连接,程序将在此处挂起等待。一旦检测到连接,将返回一个Socket对象用于与该客户端通信。Socket s = ss.accept(); - 读取数据:通过客户端 Socket 获取输入流
InputStream in = s.getInputStream(),定义缓冲区(如 2014 字节),读取数据并转换为字符串。int len = in.read(buf); String rec = new String(buf, 0, len); - 响应与关闭:可通过输出流向客户端发送反馈(如 "收到"),最后关闭 Socket。
OutputStream out = s.getOutputStream(); out.write("收到".getBytes()); s.close();
第2步:客户端连接与发送 (Socket)
目的:发起对服务端的连接,发送数据并接收响应。
入口:java.net.Socket
操作顺序:
- 建立连接:指定目标主机和端口创建 Socket 对象。
Socket s = new Socket("cj-PC", 10003); - 发送数据:获取输出流
OutputStream out = s.getOutputStream(),将待发送内容写入流中。out.write("hello".getBytes()); - 接收响应:获取输入流,读取服务端回送的消息。
byte[] bufIn = new byte[1024]; int num = in.read(bufIn); System.out.println(new String(bufIn, 0, num)); - 清理资源:关闭 Socket。由于流对象封装在 Socket 中,关闭 Socket 会自动关闭相关的输入/输出流。
s.close();
UDP 协议数据收发
UDP(用户数据报协议)是无连接的、不可靠但高效的传输方式。主要通过 DatagramSocket 和 DatagramPacket 类实现。
第1步:发送数据 (Send)
入口:java.net.DatagramSocket, java.net.DatagramPacket
操作步骤:
- 创建 Socket:实例化
DatagramSocket,可指定本地端口号(如 8888)或未指定由系统分配。DatagramSocket socket = new DatagramSocket(8888); - 封装数据包:将待发送字节数组、长度、目标主机 IP 和目标端口封装进
DatagramPacket。DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("Machine-Name"), 10086); - 发送与关闭:调用
socket.send(dp)发送数据,完成后关闭 Socket。socket.send(dp); socket.close();
第2步:接收数据 (Receive)
入口:java.net.DatagramSocket
操作步骤:
- 监听端口:创建
DatagramSocket并绑定接收端口(如 10086),以便接收发往该端口的数据报文。DatagramSocket socket = new DatagramSocket(10086); - 阻塞接收:准备接收缓冲区,创建空的
DatagramPacket对象。调用socket.receive(dp)进入阻塞状态,直到有数据到达并将数据存入数据包。DatagramPacket dp = new DatagramPacket(buf, buf.length); socket.receive(dp); - 解析数据:从数据包中提取 IP、数据和端口信息。
String ip = dp.getAddress().getHostAddress(); String data = new String(dp.getData(), 0, dp.getLength()); int port = dp.getPort(); - 持续监听:通常将接收逻辑置于循环中,以实现持续接收多组数据的目的。
基于 Socket 的文件上传实现
文件上传本质上是大数据量的流传输。以下示例展示如何将本地文件通过网络发送至服务端。
第1步:客户端读取文件并发送
目的:读取本地文件二进制数据,通过 TCP 输出流逐块发送给服务端。
关键代码逻辑:
- 建立与服务端的 Socket 连接(如端口 10005)。
- 创建
FileInputStream指向本地文件(如 "awf.jpg")。 - 定义缓冲区(如 1024 字节),循环读取文件内容至缓冲区,并将每个非空块写入 Socket 输出流。
while ((len = fis.read(buf)) != -1) { out.write(buf, 0, len); } - **重要步骤**:调用
s.shutdownOutput()。这标志着发送结束,向服务端发送一个 EOF 信号,通知服务端可以开始读取或处理完整文件,防止服务端因一直等待数据而阻塞。
第2步:服务端接收文件
目的:监听指定端口,接收客户端传入的二进制流并保存为文件。
注意:
- 服务端需通过
ServerSocket监听特定端口(如 10005)。 - 调用
accept()获取客户端 Socket,进而获取输入流。 - 在实际工程中,建议为每个
accept()产生的 Socket 开启独立线程处理,以避免阻塞其他客户端连接或服务端主逻辑。
总结
Java Socket 编程涵盖了从底层 IP 地址解析到高层数据传输的全过程。TCP 适用于需要可靠连接的场景(如文件上传、即时通讯),关键在于处理好连接的建立与流的关闭;UDP 适用于对实时性要求高、允许少量丢包的场景(如视频直播、DNS 查询),重点在于数据包的封装与解析。掌握这些核心类与方法,即可构建基本的 Java 网络应用程序。以上就是 Java Socket 编程详细内容的介绍,更多关于 Java 网络开发的基础资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













