java Socket编程调用ServerSocket的close方法

做一个简单的聊天系统服务器

服务器中有一个输入端口的控件,两个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;
    }


所以异常就产生了

这本来是个很简单的问题,但却困扰了好一会.........

猜你喜欢

转载自blog.csdn.net/msl0903/article/details/7973943