普通Socket一般分为ServerSocket和Socket两大类。
ServerSocket用于服务端,其accept()方法可以用来监听请求,该方法方法在连接传入之前一直阻塞,也就是说服务端程序会停留在该方法调用处,直到有客户端请求连接进来。accept()方法会返回一个Socket对象。
Socket用来传输数据,JDK中描述为套接字,理解起来还是有点困难。TCP用主机的IP地址加上主机上的端口号作为TCP连接的端点,这种端点就叫做套接字(socket)。一般客户端使用Socket绑定服务端IP以及监听端口发起请求并传输数据。
用大白话说就是:ServerSocket是服务端用来检测客户端是否使用Socket发起请求了,如果有,拿到Socket,从其中拿到客户端的请求数据,再将响应数据写入Socket,这其中读取写入数据又设计IO流操作。客户端使用Socket对象发送请求数据到服务端,然后在从该socket中拿到服务端的响应数据。
代码实现如下(代码中注释写的很详细):
服务端模拟实现:
/*
模拟服务器端-普通Socket实现
*/
public class Server {
public static void main(String[] args) {
try {
//创建一个ServerSocket,绑定监听端口为8080
ServerSocket serverSocket = new ServerSocket(8080);
//调用accept()方法监听客户端请求,该方法是阻塞方法,程序会停留在这里直到有客户端请求服务端的8080接口
//Socket用于通信中的数据传输
Socket socket = serverSocket.accept();
//创建BufferedReader接收来自客户端的请求数据,源数据流对象来自客户端发起请求的Socket
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String requestData = bufferedReader.readLine();
System.out.println("接收到客户端的请求数据:" + requestData);
//创建PrintWriter发送服务端响应数据,接收数据流对象也来自Socket
PrintWriter printWriter = new PrintWriter(socket.getOutputStream());
//写入响应数据
printWriter.println("服务端已接收到你的请求,响应数据为(服务端响应数据)!");
//使用flush()方法强制发送数据而不是等到缓冲区满了后才发送
printWriter.flush();
//关闭资源
printWriter.close();
bufferedReader.close();
socket.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端程序如下:
/*
模拟客户端-普通Socket实现
*/
public class Client {
public static void main(String[] args) {
try {
//创建Socket用来发起请求,设置请求IP为本机,端口号为8080
Socket socket = new Socket("127.0.0.1",8080);
//通过Socket的流对象创建PrintWriter用于发送请求数据,创建BufferedReader用于接收服务端响应数据
PrintWriter printWriter = new PrintWriter(socket.getOutputStream());
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//发送数据
String requestData = "客户端请求数据";
printWriter.println(requestData);
printWriter.flush();
//接收服务端响应数据
String responseData = bufferedReader.readLine();
System.out.println("接收到服务端的响应数据为:" + responseData);
//关闭资源
printWriter.close();
bufferedReader.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
先启动服务端程序,再启动客户端程序。输出如下:
服务端先启动后没有输出。
启动客户端后:
服务端输出:
客户端输出: