求我的聊天室客户端异常退出的处理办法!

Pro_Vida 2006-12-25 03:12:39
我做了一个聊天程序,大部分异常和BUG都处理完了,但目前还存在个bug不能解决~求各位高手帮帮我啊!!
当一个客户端用非正常手段(强行关闭)终止后会服务器和其他客户端都会出现错误,我想问题是出在了非法关闭上,因为该客户端没有在服务器上被注销。但始终想不出什么好的办法解决~强人请帮忙啊!!
//------------------------------------------------------------------------

//服务端代码:
/*
*@author Vida ,CreatDate 2006-12-23
*版本更新-与上一个把版本相同。
*/

import java.io.IOException;
import java.net.*;
import java.io.*;
import java.util.*;

public class CharServer
{
ServerSocket ss = null;

boolean bStarted = false;

ArrayList<Client> Clients = new ArrayList<Client>();


public static void main(String[] args)
{
new CharServer().start();
}

void start()
{
try
{
ss = new ServerSocket(8888);
bStarted = true;
while (bStarted)
{
Socket s = ss.accept();
System.out.println("A client Connected!");
Client c = new Client(s);
Clients.add(c);


new Thread(c).start();

}
}
catch (BindException be)
{
System.out.println("The port in use!");
System.out.println("Please bind the other one.");
}

catch (IOException e)
{
e.printStackTrace();
}

}

class Client implements Runnable
{
Socket s = null;

InputStream is = null;

OutputStream os = null;

char[] ca = new char[1024];

InputStreamReader isr = null;

BufferedReader br = null;

OutputStreamWriter osw = null;

BufferedWriter bw = null;

String str = null;

boolean bConnect = false;

int count;

public Client(Socket s)
{
this.s = s;
try
{
is = s.getInputStream();
os = s.getOutputStream();
}
catch (IOException e)
{
e.printStackTrace();
}
bConnect = true;

}

public void run()
{


isr = new InputStreamReader(is);
br = new BufferedReader(isr);


while (bConnect)
{
try
{
count = br.read(ca);
}
catch (IOException e)
{
e.printStackTrace();
}
try
{
String str = new String(ca, 0, count);
System.out.println(str);
for(int i=0; i<Clients.size(); i++)
{
Client c= Clients.get(i);
c.send(str);
}
/*Iterator<Client> it=Clients.iterator();
while(it.hasNext())
{
Client c=it.next();
c.send(str);
}*/

}
catch (StringIndexOutOfBoundsException sioobe)
{
System.out.println("The Client closed!");
bConnect = false;
try
{
br.close();
br=null;
}
catch (IOException e)
{
e.printStackTrace();
}

try
{
s.close();
s=null;
}
catch (IOException e)
{
e.printStackTrace();
}
Clients.remove(this);

}

}

}

void send(String str)
{

osw = new OutputStreamWriter(os);
bw = new BufferedWriter(osw);
try
{
bw.write(str);
}
catch (IOException e)
{
e.printStackTrace();
}
try
{
bw.flush();
}
catch (IOException e)
{
e.printStackTrace();
}

}
}
}


//-----------------------------------------------
//客户端代码
import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import java.net.*;
import java.io.*;

/*
*@author Vida ,CreatDate 2006-12-23
*版本更新-解决了关闭客户端时输入流阻塞无法退出或报出异常的问题。
*/

public class CharClinet extends Frame
{

private static final long serialVersionUID = 1L;

private Panel panel = null;

private TextArea taMessage = null;

private TextField tfTalk = null;

private Socket s = null;

OutputStreamWriter osr = null;

BufferedWriter bw = null;

InputStreamReader isr = null;

BufferedReader br = null;

Thread t = null;

char[] ca = new char[1024 * 10];

final String stLine = System.getProperty("line.separator");

boolean bConnect = false;

Thread tRec;

public CharClinet()
{
super();
initialize();
connect();
tRec=new Thread(new Receive());
tRec.start();


}

private Panel getPanel()
{
if (panel == null)
{
panel = new Panel();
panel.setLayout(new BorderLayout());
panel.add(getTaMessage(), BorderLayout.NORTH);
panel.add(getTfTalk(), BorderLayout.SOUTH);
}
return panel;
}

private TextArea getTaMessage()
{
if (taMessage == null)
{
taMessage = new TextArea("", 0, 0,
TextArea.SCROLLBARS_VERTICAL_ONLY);
taMessage.setEditable(false);
}
return taMessage;
}

private TextField getTfTalk()
{
if (tfTalk == null)
{
tfTalk = new TextField();
tfTalk.addActionListener(new TextFieldListener());
}

return tfTalk;
}

private void initialize()
{
this.setLocation(200, 200);
this.setSize(400, 300);
this.setTitle("CharClient");
this.add(getPanel(), BorderLayout.CENTER);

this.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
disconnect();
System.exit(0);
}
});
this.pack();
this.setVisible(true);
}

private void connect()
{
try
{
s = new Socket("127.0.0.1", 8888);
System.out.println("Connected a server!");
bConnect = true;
osr = new OutputStreamWriter(s.getOutputStream());
bw = new BufferedWriter(osr);
}
catch (UnknownHostException e)
{
e.printStackTrace();
}
catch (ConnectException ce)
{
System.out.println("The Server has fault ,can't to connect!");
}
catch (IOException e)
{
e.printStackTrace();
}

}

private void disconnect()
{
if (bw != null || s != null)
{
bConnect = false;
try
{
bw.close();
bw=null;
br.close();
br=null;
s.close();
s=null;
}
catch (IOException e)
{
e.printStackTrace();
}

}
else
{
System.out.println("You never to connect!");
}
}

public static void main(String[] args)
{
new CharClinet();
}

private class TextFieldListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String stTalk = tfTalk.getText().trim();
tfTalk.setText("");
/*
* taMessage.append(stTalk); taMessage.append(stLine);
*/
if (bw != null)
{
try
{

bw.write(stTalk.toCharArray());
bw.flush();

}
catch (IOException e1)
{
e1.printStackTrace();
}
}
else
{
System.out.println("Connect Error! The message counld not send !");
}
}
}

private class Receive implements Runnable
{
Receive()
{
try
{
isr = new InputStreamReader(s.getInputStream());
}
catch (IOException e)
{
e.printStackTrace();
}
br = new BufferedReader(isr);
}

public void run()
{
while (bConnect)
{
receiveMessage();
}

}

private void receiveMessage()
{
try
{
int i = br.read(ca);
taMessage.append(new String(ca, 0, i));
taMessage.append(stLine);

}
catch(SocketException e)
{
System.out.println("Client Exit!");
}
catch (IOException e)
{
e.printStackTrace();
}

}
}

}

...全文
351 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
Kinde 2006-12-25
  • 打赏
  • 举报
回复
欢迎加入QQ群:32943114
面向组件的软件开发, 专注net, java技术.
探讨新一代软件特征webOS, 第三代搜索引擎技术,P2P,Grid,动态语言, AJAX, 虚拟操作系统
fool_leave 2006-12-25
  • 打赏
  • 举报
回复
你不是把client放到一个ArrayList里面了吗

在对client io操作的时候报错的就是这个client呀,从ArrayList里面remove出来处理



不过一般这样的网络应用都是通过HashMap来存储用户的,key就是用户的名字(在用户登录的时候就知道了)。这样方便操作



反正就是谁的网络操作出错就把谁kick了,不能影响其它用户
Pro_Vida 2006-12-25
  • 打赏
  • 举报
回复
fool_leave(请及时结贴)
你怎么去判断是哪个客户端出错啊?
fool_leave 2006-12-25
  • 打赏
  • 举报
回复
代码太长了,没看

你说得问题其实很好解决。

客户端强制关闭是无法避免的,当客户端关闭后,服务端的io操作必然会出错,你需要的是一个try...catch...动作。捕捉到网络错误后就认为这个用户已经退线,or掉线,然后做相应的销毁动作就可以了
fool_leave 2006-12-25
  • 打赏
  • 举报
回复
你可以调试吗?
看看死循环因为什么造成的

应该很好解决,你调试一下看看说不定就知道了
Pro_Vida 2006-12-25
  • 打赏
  • 举报
回复
我试过了~~那个出错的客户端是remove掉了~但remove了后其他客户端进入了一个死循环!

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧