IOException: Connection refused
- 错误原因:尝试连接的服务器未在指定端口监听,或者防火墙阻止了连接。
- 处理方法:
- 检查服务器是否已正确启动并监听指定端口。可以使用工具如
netstat
(在Linux系统)或 netstat -ano
(在Windows系统)来确认端口监听情况。
- 检查防火墙设置,确保客户端到服务器的连接端口未被阻止。在Linux系统,可以通过
iptables
命令来配置防火墙规则;在Windows系统,可以在控制面板的防火墙设置中允许相关程序或端口通过。
IOException: Resource temporarily unavailable
- 错误原因:在非阻塞模式下,当尝试进行I/O操作(如读取或写入)时,资源暂时不可用,这是因为非阻塞I/O不会等待操作完成,而是立即返回。例如,在没有数据可读时调用
read
方法。
- 处理方法:
- 实现适当的重试逻辑。可以使用一个循环来定期重试I/O操作,直到操作成功或达到最大重试次数。例如,在Java中:
int maxRetries = 10;
int retryCount = 0;
while (true) {
try {
int bytesRead = socketChannel.read(buffer);
if (bytesRead > 0) {
// 处理读取到的数据
break;
}
} catch (IOException e) {
if (e instanceof java.nio.channels.OverlappingFileLockException) {
if (retryCount < maxRetries) {
try {
Thread.sleep(100); // 等待一段时间后重试
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
retryCount++;
} else {
// 达到最大重试次数,处理错误
throw new RuntimeException("Max retry count reached", e);
}
} else {
throw new RuntimeException("Unexpected I/O error", e);
}
}
}
ClosedChannelException
- 错误原因:在进行I/O操作时,相关的通道(如
SocketChannel
)已被关闭。这可能是由于程序逻辑中错误地关闭了通道,或者远程端关闭了连接。
- 处理方法:
- 在进行I/O操作前,先检查通道是否处于打开状态。在Java中,可以通过
socketChannel.isOpen()
方法来检查。
- 捕获
ClosedChannelException
异常,在捕获块中进行适当的处理,比如记录日志并关闭相关资源,或者尝试重新建立连接。例如:
try {
int bytesRead = socketChannel.read(buffer);
} catch (ClosedChannelException e) {
// 记录日志
System.err.println("Channel is closed: " + e.getMessage());
// 关闭其他相关资源
socketChannel.close();
// 尝试重新建立连接
// 重新创建SocketChannel并连接到服务器
SocketChannel newChannel = SocketChannel.open();
newChannel.connect(new InetSocketAddress(serverAddress, serverPort));
} catch (IOException e) {
// 处理其他I/O异常
e.printStackTrace();
}
BindException: Address already in use
- 错误原因:尝试绑定到一个已经被其他进程使用的端口。
- 处理方法:
- 查找占用该端口的进程并终止它。在Linux系统,可以使用
lsof -i :port
命令找到占用端口的进程PID,然后使用 kill -9 PID
命令终止进程(使用 kill -9
要谨慎,因为这是强制终止进程)。在Windows系统,可以使用 netstat -ano | findstr :port
找到PID,然后在任务管理器中终止对应的进程。
- 选择一个未被占用的端口进行绑定。可以通过随机选择一个在可用范围内(如1024 - 65535)的端口,或者配置应用程序从一个端口列表中选择可用端口。
SelectorClosedException
- 错误原因:在使用
Selector
进行多路复用I/O时,Selector
已被关闭,而程序仍尝试在该 Selector
上注册通道或执行选择操作。
- 处理方法:
- 在使用
Selector
的代码中,增加对 SelectorClosedException
的捕获。例如:
try {
int readyChannels = selector.select();
if (readyChannels > 0) {
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
while (keyIterator.hasNext()) {
SelectionKey key = keyIterator.next();
// 处理就绪的通道
keyIterator.remove();
}
}
} catch (SelectorClosedException e) {
// 重新创建Selector并重新注册通道
Selector newSelector = Selector.open();
socketChannel.register(newSelector, SelectionKey.OP_READ);
} catch (IOException e) {
// 处理其他I/O异常
e.printStackTrace();
}