上论坛的时候,经常会有些朋友求一个简单聊天室的程序。有的要求有界面,但,大多数朋友,不要太复杂滴。 我这里,正好有一个简单滴,客户端只需要Telnet登录上来,输入用户名,就可以聊天了。 以下是服务端的代码: import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.concurrent.ConcurrentLinkedQueue; /** * 简单聊天室程序 */ public class EasyChatRoom { public static final int port = 10000;// Server端的监听端口 private static volatile boolean running = true;// 由于是阻塞模式, // 所以该变量为false时,主线程仍可能未及时停止,而处在端口监听的阻塞状态。 public static void main(String args[]) {// 主线程的入口方法 ServerSocket server = null; try { server = new ServerSocket(port); System.out.println("Server start up on port :" + port); while (running) {// 一般情况下,在while循环体中没有break语句时, // 不赞同while条件是常量true这种编程方式。 Socket s = server.accept();// 阻塞模式的监听方法 UserHandler user = new UserHandler(s); new Thread(user).start(); } } catch (Exception e) { e.printStackTrace(); } finally { if (server != null && !server.isClosed()) { try { server.close(); } catch (Exception e) { } } } } } class UserHandler implements Runnable { /** 用于存放所有客户端处理器对象 */ private static final ConcurrentLinkedQueue<UserHandler> users = new ConcurrentLinkedQueue<UserHandler>(); private Socket s; private String userName; private PrintWriter writer; private BufferedReader reader; private volatile boolean running = true; public UserHandler(Socket s) { this.s = s; users.add(this);// 注意users对象是静态变量, // 所以,一个类无论有多少个对象,都只拥有一个users对象 } public void run() { try { reader = new BufferedReader(new InputStreamReader(s.getInputStream())); writer = new PrintWriter(new OutputStreamWriter(s.getOutputStream()), true); sendMessage("welcome u ,enter your name :"); userName = reader.readLine(); sendAll(userName + " has join us "); long lastTime = 0; while (running) { String line = reader.readLine(); long nowTime = System.currentTimeMillis(); // 检测不向其他客户端发送信息的条件。 if (checkDenyCondition(line, nowTime, lastTime)) continue; lastTime = nowTime; if (line.equals("bye")) {// 检测客户端准备离开的条件 sendAll(userName + " leave us "); break; } sendAll(userName + " said :" + line); } } catch (Exception e) { // e.printStackTrace(); } finally { users.remove(this);// 最后清除本客户端处理器对象 if (s != null) try { s.close(); } catch (Exception e) { } } } /** * 如果客户端接连总发消息,或者,发送空消息,则这些消息将不被发送给其他用户 */ private boolean checkDenyCondition(String line, long nowTime, long lastTime) { if (nowTime - lastTime < 3000 || line == null || line.trim().length() == 0) { sendMessage("flush denied "); return true; } return false; } public synchronized void sendMessage(String message) { writer.println(message); writer.flush(); } public void sendAll(String message) { Iterator<UserHandler> itr = users.iterator(); try { while (itr.hasNext()) { itr.next().sendMessage(message); } } catch (NoSuchElementException ex) { }//当users对象中待迭代的下一个对象被其他线程删除时抛出该异常 } }