做一个简单的聊天系统服务器
服务器中有一个输入端口的控件,两个JButton按钮“停止”和“运行”
点击“运行”按钮,启动服务器
点击“停止”按钮,调用ServerSocket的close方法,停止服务器。
上部分代码:
btn_ok.setText("运行");
btn_ok.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
String strPort = port.getText().trim();
try {
serverSocket = new ServerSocket(Integer.parseInt(strPort));
System.out.println("服务器已启动");
btn_ok.setEnabled(false);
} catch (NumberFormatException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
//消息分发
new Thread(new MsgRunnable()).start();
}
btn_quit.setText("停止");
btn_quit.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent e) {
try {
if(serverSocket!=null){
serverSocket.close();
isRun = false;
btn_ok.setEnabled(true);
}
else{
JOptionPane.showMessageDialog(null, "服务还未启动,请启动服务再停止");
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
class MsgRunnable implements Runnable{
@Override
public void run() {
while(true){
try {
if(!serverSocket.close()){
Socket socket = serverSocket.accept();
System.out.println("服务器正在监听");
ClientPro cp = new ClientPro(socket);
cp.start();
addConnetion(socket, cp);
}
else{
JOptionPane.showMessageDialog(null, "服务器已关闭");
return;
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
根据我的想法,点击“停止”时,serverSocket关闭,那么 分发线程中的if(!serverSocket.close())会执行判断,弹出服务器已关闭对话框,看起来好像挺符合代码的逻辑的。
但是实际运行时,却报Socket close异常。
于是各种调试,终于发现异常是分发线程的e1.printStackTrace();
扫描二维码关注公众号,回复:
4032018 查看本文章
但为什么会报异常呢?
因为ServerSocket的accept方法是个当前线程阻塞方法,当它只有接受一个客户端链接时,才会往下执行,我们启动服务器后,进入serverSocket.accept方法
它就一直在等待客户端的链接,所以它虽然是个无限循环线程,但判定条件却是多余的(当然,前提是你没进入accept方法)。
这时突然我们的另一个线程将serverSocket关闭了,那么看下我们accept方法的源代码:
public Socket accept() throws IOException {
if (isClosed())
throw new SocketException("Socket is closed");
if (!isBound())
throw new SocketException("Socket is not bound yet");
Socket s = new Socket((SocketImpl) null);
implAccept(s);
return s;
}
所以异常就产生了
这本来是个很简单的问题,但却困扰了好一会.........