先贴代码:
package chat;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import java.io.IOException;
import java.net.ServerSocket;
public class MyUI {
static final String NET_DISCON_FLAG="%%##DISCONNECT##%%";
JTextArea disparea;
JTextArea sendarea;
ServerSocket ss;
Socket s;
Thread rec;
boolean net_flag=false; // the other side is online
InputStream in;
DataInputStream din;
OutputStream out;
DataOutputStream dout;
int port;
MyUI(int port) {
this.port = port;
JFrame frm = new JFrame();
JPanel pl1 = new JPanel();
JPanel pl2 = new JPanel();
JPanel pb = new JPanel();
disparea = new JTextArea();
disparea.setEditable(false);
sendarea = new JTextArea();
JScrollPane scrop = new JScrollPane(disparea);
JScrollPane editp = new JScrollPane(sendarea);
JButton btnsnd = new JButton("Send");
btnsnd.addActionListener(new clsbtnsend());
//pl1.setLayout(new GridLayout(2,1));
pl1.setLayout(new BorderLayout());
pl1.add(scrop,BorderLayout.CENTER);
pl2.setLayout(new BorderLayout());
pl2.add(editp,BorderLayout.CENTER);
pl2.add(btnsnd,BorderLayout.EAST);
frm.setLayout(new BorderLayout());
frm.addWindowListener(new clswindowclose());
frm.add(pl1,BorderLayout.CENTER);
frm.add(pl2,BorderLayout.SOUTH);
frm.setSize(300, 550);
frm.setVisible(true);
try {
ss= new ServerSocket(port);
s = ss.accept();
//System.out.println("a client connect");
disparea.setText("a client connect");
} catch (IOException e) {
e.printStackTrace();
}
rec = new Thread(new recvpro());
rec.start();
}
class recvpro implements Runnable {
public void run() {
System.out.println("in recvpro");
// TODO Auto-generated method stub
if(in==null || din==null) {
try {
in = s.getInputStream();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
din = new DataInputStream(in);
}
System.out.println("server alive");
while(s.isConnected()) {
try {
String recv =din.readUTF();
if(!recv.equalsIgnoreCase(NET_DISCON_FLAG))
disparea.setText( disparea.getText()+"\n"+recv);
else {
net_flag=true;
disparea.setText( disparea.getText()+"\n"+"TERMINATED");
return;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// if(!s.isConnected())
// disparea.setText("cun down");
}
}
class clsbtnsend implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if( out == null || dout==null)
try {
out = s.getOutputStream();
dout = new DataOutputStream(out);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
dout.writeUTF(sendarea.getText());
dout.flush();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
disparea.setText(disparea.getText()+"\n"+sendarea.getText());
sendarea.setText("");
}
}
class clswindowclose extends WindowAdapter {
public void windowClosing(WindowEvent e){
if(rec!=null)
if(rec.isAlive())
rec.interrupt();
try {
if(!net_flag && dout!=null) {
dout.writeUTF(NET_DISCON_FLAG);
dout.flush();
}
if(din!=null)
din.close();
if(in!=null)
in.close();
if(dout!=null)
dout.close();
if(out!=null)
out.close();
} catch (IOException e3) {
// TODO Auto-generated catch block
e3.printStackTrace();
}
if(s != null)
try {System.out.println("flag1");
s.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if(ss != null)
try {System.out.println("flag2");
ss.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println("window close ");
//super.windowClosing(e);
}
}
}
最近做一个聊天的小程序,运用多线程接收,发送则使用事件方式。
然后出了一堆bug,在调bug过程中,(在如上的代码的情况下)发现即便是在windowclosing函数中处理一切,
运行代码,然后不做操作直接关闭
依旧会报错。错误提示socket closed,错误指向在多线程的run方法里面。
于是加了几个syso来看原因,运行结果如下:
flag2
java.net.SocketException: socket closed
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:384)
at java.net.ServerSocket.implAccept(ServerSocket.java:453)
at java.net.ServerSocket.accept(ServerSocket.java:421)
at chat.MyUI.<init>(MyUI.java:69)
at chat.chat.main(chat.java:14)
window close
in recvpro
Exception in thread "Thread-3" java.lang.NullPointerException
at chat.MyUI$recvpro.run(MyUI.java:91)
at java.lang.Thread.run(Thread.java:619)
猜测原因应该是即便是关闭窗口,执行windowclosing函数,主函数仍会执行完毕,因此导致报错。