Java Socket编程详解:TCP客户端与服务器端实现指南
Socket是计算机网络通信的基础技术,广泛用于浏览器、即时通讯等场景。本文聚焦Java环境下的TCP/IP Socket编程,解析TCP与UDP协议差异,并通过客户端与服务端代码示例,展示从建立连接、数据读写到资源释放的完整流程,帮助开发者快速掌握Java网络编程核心技能。
TCP与UDP协议的选择
在Java中进行Socket编程前,需理解底层传输协议的特性。Java的类BSD IPC接口位于TCP/UDP协议之上,通过Socket地址(IP+端口)标识通信端点。
第1步:理解UDP数据报通信
目的:了解无连接通信机制。
特性:UDP是无连接协议,每次发送需附带源和目标的Socket描述符,存在额外开销。数据报大小限制为64KB,且不可靠,不保证顺序或送达。
适用场景:实时性高或容错率高的服务(如局域网视频流、DNS查询),因其轻量且丢包影响小。
第2步:掌握TCP流通信
目的:理解可靠数据传输机制。
特性:TCP是基于连接的协议。通信前需建立“三次握手”连接,虽增加耗时,但保证数据按序到达且无误。
适用场景:远程登录(Telnet)、文件传输(FTP)及Web服务,适用于数据量大且要求准确性的场景。
鉴于TCP的广泛通用性和可靠性,下文示例均基于TCP/IP协议展开。所有相关类均位于java.net包下。
Java TCP Socket编程实战
Java Socket编程遵循Unix标准的Open-Read-Write-Close模型。我们需要分别实现服务端监听和客户端连接逻辑。
第3步:编写服务器端代码 (ServerSocket)
目的:创建监听端口并接收客户端请求。
入口:新建ServerSocket实例。
动作:指定端口后调用accept()方法。该方法为阻塞式,直到有客户端连接才返回Socket对象。
参数:端口号建议大于1023(避免占用系统预留端口如80, 443等)。
完成状态:成功获取socket对象,即可进行后续IO操作。
public class ServerClient {
public static void main(String[] args) {
int port = 8919; // 自定义非保留端口
try {
ServerSocket server = new ServerSocket(port);
System.out.println("Server started, listening on port " + port);
// accept() 阻塞直到客户端连接
Socket socket = server.accept();
// 读取数据
Reader reader = new InputStreamReader(socket.getInputStream());
char chars[] = new char[1024];
int len;
StringBuilder builder = new StringBuilder();
while ((len=reader.read(chars)) != -1) {
builder.append(new String(chars, 0, len));
}
System.out.println("Receive from client message=: " + builder);
// 清理资源
reader.close();
socket.close();
server.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
第4步:编写客户端代码 (Socket)
目的:连接指定服务器并发送数据。
入口:新建Socket实例,传入主机IP和端口。
动作:通过getOutputStream()获取输出流,写入数据后刷新并关闭。
参数:host通常为"127.0.0.1"(本地测试),port需与服务端一致。
完成状态:服务端打印出客户端发送的消息即表示通信成功。
public class ClientSocket {
public static void main(String args[]) {
String host = "127.0.0.1";
int port = 8919;
try {
// 发起连接
Socket client = new Socket(host, port);
// 获取输出流并发送数据
Writer writer = new OutputStreamWriter(client.getOutputStream());
writer.write("Hello From Client");
writer.flush();
writer.close();
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
第5步:实现回声服务器 (Echo Server)
目的:验证双向通信及循环接收能力。
逻辑:服务器持续接收客户端数据,并将其原样返回。
注意:生产环境中需处理多并发(建议使用线程池),此处仅展示单连接回声逻辑。
import java.io.*;
import java.net.*;
public class EchoServer {
public static void main(String args[]) {
ServerSocket echoServer = null;
Socket clientSocket = null;
try {
// 在9999端口启动服务
echoServer = new ServerSocket(9999);
// 接受一个连接
clientSocket = echoServer.accept();
DataInputStream is = new DataInputStream(clientSocket.getInputStream());
PrintStream os = new PrintStream(clientSocket.getOutputStream());
String line;
// 循环读取直到断开连接
while ((line = is.readLine()) != null) {
os.println(line); // 回声反馈
}
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
} finally {
// 确保资源释放
try { if (clientSocket != null) clientSocket.close(); }
catch (IOException e) { e.printStackTrace(); }
try { if (echoServer != null) echoServer.close(); }
catch (IOException e) { e.printStackTrace(); }
}
}
}
可通过命令行工具测试上述回声服务:
$ curl http://127.0.0.1:9999/?test
最佳实践与注意事项
- 端口选择:务必避开0-1023系统保留端口,推荐使用1024以上的未占端口。
- 资源管理:IO操作必须伴随
close()调用,建议在finally块中执行,防止内存泄漏或句柄耗尽。 - API规范:优先使用
java.net包下的标准API,避免使用已弃用或不跨平台兼容的sun.*内部包。 - 异常处理:网络IO极易受环境干扰(如断网、超时),完善的try-catch机制是必要的。
以上就是Java Socket编程的详细内容,更多关于Java网络编程的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













