Java BIO面试题及代码示例

1. 什么是BIO(Blocking I/O)?

BIO,即阻塞式I/O,是指在Java中进行输入输出操作时,若数据未到达或未准备好,则当前线程会阻塞,直到数据准备就绪。

2. BIO的工作模式是什么?

BIO的工作模式是一对一的请求-响应模式,即每个客户端连接都需要一个单独的线程来处理。

3. 如何在Java中创建BIO服务器?

使用ServerSocket类创建服务器端的Socket,并监听客户端的连接请求。

ServerSocket serverSocket = new ServerSocket(portNumber);
Socket clientSocket = serverSocket.accept(); // 阻塞,直到一个连接建立

4. 如何在Java中创建BIO客户端?

使用Socket类创建客户端Socket,并连接到服务器。

Socket socket = new Socket(host, port);

5. BIO中如何读取数据?

通过InputStream读取数据,如果数据未到达,则调用read()方法的线程将被阻塞。

InputStream inputStream = socket.getInputStream();
byte[] buffer = new byte[1024];
int bytesRead = inputStream.read(buffer); // 阻塞,直到有数据可读

6. BIO中如何写入数据?

通过OutputStream写入数据。

OutputStream outputStream = socket.getOutputStream();
outputStream.write("Hello Server".getBytes());

7. BIO的线程模型是什么?

BIO通常采用一请求一响应的线程模型,每个连接都由一个独立的线程处理。

8. BIO适用于什么场景?

BIO适用于连接数较少的场合,如小型应用或传统的桌面应用。

9. BIO中如何处理多个客户端连接?

为每个客户端连接创建一个新的线程,或者使用线程池管理多个线程。

10. BIO的`accept`方法是如何工作的?

accept方法在服务器端用于接受客户端的连接请求,如果无连接请求,则调用accept的线程将被阻塞。

11. BIO中如何关闭连接?

通过调用Socket的close方法关闭连接。

socket.close();

12. BIO中如何处理I/O异常?

捕获并处理IOException

try {
    socket.close();
} catch (IOException e) {
    e.printStackTrace();
}

13. BIO中如何设置Socket选项?

使用setSoTimeoutsetTcpNoDelay等方法设置Socket选项。

socket.setSoTimeout(1000); // 设置读取超时时间为1000毫秒

14. BIO中如何获取Socket的输入流和输出流?

通过getInputStreamgetOutputStream方法获取。

InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream();

15. BIO中如何监听多个端口?

创建多个ServerSocket实例,每个实例监听不同的端口。

16. BIO中如何实现简单的回显服务器?

创建ServerSocket监听端口,接受客户端连接,并在独立的线程中读取客户端发送的数据,然后将数据发送回客户端。

while (true) {
    Socket clientSocket = serverSocket.accept();
    new Thread(new EchoClientHandler(clientSocket)).start();
}

17. BIO中如何优化性能?

由于BIO是阻塞式的,性能优化通常涉及减少I/O操作的阻塞时间,或者使用线程池减少线程创建和销毁的开销。

18. BIO中如何安全地关闭Socket?

在关闭Socket之前,应该先关闭输入流和输出流。

InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream();
inputStream.close();
outputStream.close();
socket.close();

19. BIO中如何处理半关闭状态?

当TCP连接的一方向另一方发送了FIN包,表示不再发送数据,但仍然可以接收数据,这时连接处于半关闭状态。

20. BIO中如何设置Socket的发送和接收缓冲区大小?

使用setSendBufferSizesetReceiveBufferSize方法设置。

socket.setSendBufferSize(1024);
socket.setReceiveBufferSize(1024);

21. BIO中如何检测Socket是否已经关闭?

检查isClosed方法的返回值。

boolean isClosed = socket.isClosed();

22. BIO中如何设置Socket的超时时间?

使用setSoTimeout方法设置。

socket.setSoTimeout(5000); // 设置读取超时时间为5000毫秒

23. BIO中如何实现客户端的连接超时?

捕获SocketTimeoutException异常。

try {
    socket.connect(new InetSocketAddress(host, port), timeout);
} catch (SocketTimeoutException e) {
    System.err.println("Connection timed out");
}

24. BIO中如何设置Socket的KeepAlive选项?

使用setKeepAlive方法设置。

socket.setKeepAlive(true);

25. BIO中如何设置Socket的ReuseAddress选项?

使用setReuseAddress方法设置。

serverSocket.setReuseAddress(true);

26. BIO中如何设置Socket的linger选项?

使用setSoLinger方法设置。

socket.setSoLinger(true, 0);

27. BIO中如何设置Socket的流量类?

使用setTrafficClass方法设置。

socket.setTrafficClass(0x04); // 设置为TCP拥塞控制

28. BIO中如何使用多路复用?

Java中的java.net.ServerSocket不支持多路复用,但可以通过外部库或JNI调用本地代码实现。

29. BIO中如何提高服务器的并发处理能力?

可以通过多线程或线程池来提高并发处理能力,每个线程处理一个客户端连接。

30. BIO中如何避免客户端连接的并发问题?

确保客户端的连接请求在一个线程内顺序处理,避免并发修改共享资源。