在Java中编写服务端和客户端程序通常涉及到网络通信,最常见的网络协议是TCP和UDP。这里,将以TCP协议为例,展示如何使用Java的ServerSocket
和Socket
类来编写一个简单的服务端和客户端程序 。
一、TCP服务端
服务端的主要任务是监听来自客户端的连接请求,并处理这些连接。
1.服务端实现步骤:
(1)创建ServerSocket
实例:通过指定端口号来创建一个ServerSocket
实例,这个实例将监听该端口上的连接请求。
(2)等待并接受连接:使用ServerSocket
的accept()
方法来等待并接受客户端的连接请求。这个方法会阻塞,直到有客户端连接为止。一旦有客户端连接,它会返回一个Socket
实例,该实例代表了与服务端之间的连接。
(3)获取输入流和输出流:通过客户端连接返回的Socket
实例,服务端可以获取输入流(InputStream
)和输出流(OutputStream
),用于读取客户端发送的数据和向客户端发送数据。
(4)处理数据:服务端读取客户端发送的数据,进行相应处理(如计算、存储等),然后将处理结果发送回客户端。
(5)关闭连接:处理完数据后,关闭与客户端的连接,释放资源。
package com.apesource.tcp;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
// 服务端:首先启动,等待客户端连接
public class Server {
public static void main(String[] args) {
// 创建服务端Socket对象,监听8848端口
try(ServerSocket serverSocket = new ServerSocket(8848)) {
while (true){
// 服务器端启动,并进入”等待状态“(等待某一个客户端的连接)
// 当如果没有客户端连接时,accept()处于等在阻塞状态
// 当如果发现客户端连接时,accept()返回当前正在连接的客户端Socket
Socket clientSocket = serverSocket.accept();
InetAddress clientNetAddress = clientSocket.getInetAddress();
System.out.printf("客户端%s正在连接服务端...\n",clientNetAddress.getHostAddress());
// 服务端读取来自客户端的一条信息
BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String message = reader.readLine();
System.out.printf("客户端%s说:%s\n",clientNetAddress.getHostAddress(),message);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
二、 TCP客户端
客户端的主要任务是连接到服务端,并发送数据给服务端,以及接收服务端的响应。
1.客户端实现步骤:
(1)创建Socket
实例:通过指定服务端的IP地址和端口号来创建一个Socket
实例,这个实例将尝试连接到服务端。
(2)获取输出流和输入流:通过Socket
实例,客户端可以获取输出流(OutputStream
)和输入流(InputStream
),用于向服务端发送数据和从服务端接收数据。
(3)发送数据:客户端通过输出流向服务端发送数据。
(4)接收响应:客户端通过输入流读取服务端发送的响应数据。
(5)关闭连接:完成数据交换后,关闭与服务端的连接,释放资源
package com.apesource.tcp;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
// 客户端:在服务器启动后,向服务端发送一个连接的请求
public class Client {
public static void main(String[] args) {
// 创建客户端Socket对象,来凝结指定IP和端口
try(Socket clientSocket = new Socket("192.168.199.112",8848)) {
// 客户端向服务端发送一条信息(输出流)
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(clientSocket.getOutputStream()));
writer.write("hello~你好"); // 写入缓冲区(内存)
writer.flush(); // 清空缓冲区,发送至网络
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行说明
- 首先运行
Server
类,启动服务端。 - 然后运行
Client
类,启动客户端。 - 观察服务端和客户端的响应。
注意事项
- 确保服务端和客户端的端口号一致。
- 服务端必须先运行,客户端才能成功连接。
- 数据的发送和接收可能会遇到阻塞或异常,因此需要进行适当的异常处理和错误检测。
- 在关闭资源时,应该确保先关闭流(如
BufferedReader
等),再关闭Socket
,以避免资源泄漏。这里我们使用了try-catch语句来自动关闭资源。 - 实际应用中,网络编程需要考虑异常处理、多线程(处理多个客户端连接)等复杂情况。