Java实现TCP通信(附带实例)
我们使用 Java 进行 TCP 通信编程时,实际上就是两台计算机上的两个进程进行跨机器通信。

图 1 TCP通信
如图 1 所示,此时需要将其中一台计算机上的进程当作服务器端,它对应的是 ServerSocket 类,由它先启动并监听某个指定的端口。另一台计算机上的进程当作客户端,它对应的是 Socket 类,由它指定服务器端的 IP 地址和端口。客户端一旦成功连接服务器端就表示建立了 TCP 连接,双方就能互相发送和接收数据。
ServerSocket 类实现了服务器端套接字功能,该类位于 java.net 包中。该类包含了 4 种构造方法:
Socket 类实现了客户端套接字功能,该类位于 java.net 包中。该类有下面三种常用的构造方法:
下面具体看如何实现服务器端和客户端的通信。服务器端的代码如下所示:
为了简化代码,这里的逻辑是完成一次响应后便把 ServerSocket 关闭。服务器端的程序启动后输出“服务器端套接字正在等待客户端的连接”,然后就一直阻塞等待客户端的连接。
客户端的代码如下所示:
服务器端的输出结果:
客户端的输出结果:
通过上面的通信例子我们已经了解了如何使用套接字,服务器端和客户端的套接字使用存在一些不同,下面我们总结一下服务器端和客户端的套接字使用步骤。
服务器端:
客户端:

图 1 TCP通信
如图 1 所示,此时需要将其中一台计算机上的进程当作服务器端,它对应的是 ServerSocket 类,由它先启动并监听某个指定的端口。另一台计算机上的进程当作客户端,它对应的是 Socket 类,由它指定服务器端的 IP 地址和端口。客户端一旦成功连接服务器端就表示建立了 TCP 连接,双方就能互相发送和接收数据。
ServerSocket 类实现了服务器端套接字功能,该类位于 java.net 包中。该类包含了 4 种构造方法:
ServerSocket() ServerSocket(int port) ServerSocket(int port, int backlog) ServerSocket(int port, int backlog, InetAddress bindAddr)
- 第一种表示创建服务端套接字对象但不绑定端口;
- 第二种表示创建服务端套接字对象并且绑定指定端口;
- 第三种表示创建服务端套接字对象、绑定指定端口并且指定在繁忙时最大的客户端积压量;
- 第四种是在第三种的基础上指定服务器端地址。
Socket 类实现了客户端套接字功能,该类位于 java.net 包中。该类有下面三种常用的构造方法:
Socket() Socket(String host, int port) Socket(InetAddress address, int port)
- 第一种表示创建一个未连接的套接字对象;
- 第二种表示创建一个套接字对象并连接到指定的地址和端口上;
- 第三种表示创建一个套接字对象并连接到指定的 IP 地址和端口上。
下面具体看如何实现服务器端和客户端的通信。服务器端的代码如下所示:
public class TCPSocketServer { public static void main(String[] args) { ServerSocket serverSocket = null; try { serverSocket = new ServerSocket(8888); System.out.println("服务器端套接字正在等待客户端的连接"); Socket socket = serverSocket.accept(); System.out.println("成功接收一个客户端套接字连接"); DataOutputStream dos = new DataOutputStream(socket.getOutputStream()); DataInputStream dis = new DataInputStream(socket.getInputStream()); System.out.println("客户端发送的数据:" + dis.readUTF()); dos.writeUTF("你好,客户端!"); socket.close(); serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } }首先创建 ServerSocket 对象并绑定本地 端口,然后调用 accept() 方法等待客户端的连接,程序会阻塞在这里等待客户端连接,一旦有客户端连接就会创建一个套接字并返回。接着获取套接字的输入流和输出流,输入流用于获取客户端传输的数据,而输出流则用来向客户端响应发送数据。最后在数据处理完后关闭套接字。
为了简化代码,这里的逻辑是完成一次响应后便把 ServerSocket 关闭。服务器端的程序启动后输出“服务器端套接字正在等待客户端的连接”,然后就一直阻塞等待客户端的连接。
客户端的代码如下所示:
public class TCPSocketClient { public static void main(String[] args) { Socket socket = null; try { socket = new Socket("localhost", 8888); DataOutputStream dos = new DataOutputStream(socket.getOutputStream()); DataInputStream dis = new DataInputStream(socket.getInputStream()); System.out.println("准备向服务器端发送数据"); dos.writeUTF("我是客户端!"); System.out.println("准备读取服务器端数据"); System.out.println(dis.readUTF()); socket.close(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }我们知道服务器端的 8888 端口已经处于监听状态,客户端如果要与之通信则要先指定服务器端 IP 地址与端口并创建一个套接字对象,注意“localhost”是一个特殊的地址,表示当前本地计算机。接着同样是获取套接字的输出流与输入流,输出流用于向服务器端发送数据,输入流用于读取服务器端发送过来的数据。最后当交互处理完后关闭套接字。
服务器端的输出结果:
服务器端套接字正在等待客户端的连接
成功接收一个客户端套接字连接
客户端发送的数据:我是客户端!
客户端的输出结果:
准备向服务器端发送数据
准备读取服务器端数据
你好,客户端!
通过上面的通信例子我们已经了解了如何使用套接字,服务器端和客户端的套接字使用存在一些不同,下面我们总结一下服务器端和客户端的套接字使用步骤。
服务器端:
- 创建 ServerSocket 对象;
- 将 ServerSocket 对象绑定一个指定的端口,通常这一步可以直接由构造方法完成;
- 调用 accept() 方法使 ServerSocket 对象开始监听客户端的套接字连接;
- 编写成功接收到客户端连接后的处理逻辑,通过输入流和输出流分别读取客户端数据和向客户端发送数据;
- 处理结束后关闭 ServerSocket 对象。
客户端:
- 创建 Socket 对象;
- Socket 对象对指定 IP 地址和端口发起连接,通常这一步直接由构造方法完成;
- 获取 Socket 对象的输出流以便向服务器端发送数据;
- 获取 Socket 对象的输入流以便读取服务器端发送过来的数据;
- 关闭 Socket 对象。