(三)阻塞式编程BIO
1.Socket与ServerSocket
- 如果收到客户端的请求后,accept函数会返回一个Socket对象。该对象是服务器用于和客户端通信的端点。
- accept函数是阻塞式的,直到收到客户端的请求。
2.简单演示Socket与ServerSocket的基本使用
目标:客户端连接到服务器后,发送消息,服务器收到后,把消息原封不动的发回去。
2.1服务器端
public class Server { public static void main(String[] args) { final String QUIT = "quit"; final int DEFAULT_PORT = 8888; // 服务器端使用8888作为监听端口 ServerSocket serverSocket = null; // 1.绑定监听端口 try { serverSocket = new ServerSocket(DEFAULT_PORT); // 创建ServerSocket实例 System.out.println("启动服务器,监听端口" + DEFAULT_PORT); while (true) { // 2.等待客户端连接,accept()函数是阻塞式的 Socket socket = serverSocket.accept(); System.out.println("客户端[" + socket.getPort() + "]已连接"); // 3.获取IO流 BufferedReader reader = new BufferedReader( new InputStreamReader(socket.getInputStream()) // InputStreamReader:将InputStream转换为Reader ); BufferedWriter writer = new BufferedWriter( new OutputStreamWriter(socket.getOutputStream()) ); // 4.读取客户端发送的消息 String msg = null; while ((msg = reader.readLine()) != null) { // readLine()返回分隔符前的所有信息 System.out.println("客户端[" + socket.getPort() + "]" + msg); // 5.回复客户发送的消息 writer.write("服务器:" + msg + "\n"); writer.flush(); // 防止有遗留的消息留在缓冲区 // 查看客户端是否退出 if (QUIT.equals(msg)) { System.out.println("客户端[" + socket.getPort() + "]已断开连接" ); break; } } } } catch (IOException e) { e.printStackTrace(); } finally { // 6.不管是否有异常,都可安全的关闭资源 if (serverSocket != null) { try { serverSocket.close(); System.out.println("关闭serverSocket"); } catch (IOException e) { e.printStackTrace(); } } } } }
2.2客户端
public class Client { public static void main(String[] args) { final String QUIT = "quit"; final String DEFAULT_SERVER_HOST = "127.0.0.1"; final int DEFAULT_SERVER_PORT = 8888; Socket socket = null; BufferedWriter writer = null; // 1.创建Socket try { socket = new Socket(DEFAULT_SERVER_HOST, DEFAULT_SERVER_PORT); // 2. 创建IO流 BufferedReader reader = new BufferedReader( new InputStreamReader(socket.getInputStream()) ); writer = new BufferedWriter( new OutputStreamWriter(socket.getOutputStream()) ); // 3.等待用户输入信息 BufferedReader consoleReader = new BufferedReader( new InputStreamReader(System.in) // System.in:标准的输入流,默认从键盘输入 ); while (true) { String input = consoleReader.readLine(); // 4.发送消息给服务器 writer.write(input + "\n"); // 加上分隔符,为了保证readLine()触发 writer.flush(); // 5.读取服务器返回的消息 String msg = reader.readLine(); System.out.println(msg); // 查看用户是否退出 if (QUIT.equals(input)) { break; } } } catch (IOException e) { e.printStackTrace(); } finally { // 关闭外层流的同时,内层流也会自动关闭,因此如果关闭writer,那么socket也会被关闭 if (writer != null) { try { writer.close(); System.out.println("关闭socket"); } catch (IOException e) { e.printStackTrace(); } } } } }
2.3响应结果
3. 拓展练习