浏览 23761 次
锁定老帖子 主题:java多线程控制台聊天室
精华帖 (0) :: 良好帖 (0) :: 新手帖 (1) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-04-11
最后修改:2009-04-11
聊天室服务器端 package tf.thread; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ChatServer { private static final int PORT = 8888; // 端口号 private static List<Socket> list = new ArrayList<Socket>(); // 保存连接对象 private ExecutorService exec; private ServerSocket server; public static void main(String[] args) { new ChatServer(); } public ChatServer() { try { server = new ServerSocket(PORT); exec = Executors.newCachedThreadPool(); System.out.println("服务器已启动!"); Socket client = null; while (true) { client = server.accept(); // 接收客户连接 list.add(client); exec.execute(new ChatTask(client)); } } catch (IOException e) { e.printStackTrace(); } } static class ChatTask implements Runnable { private Socket socket; private BufferedReader br; private PrintWriter pw; private String msg; public ChatTask(Socket socket) throws IOException { this.socket = socket; br = new BufferedReader(new InputStreamReader(socket .getInputStream())); msg = "【" + this.socket.getInetAddress() + "】进入聊天室!当前聊天室有【" + list.size() + "】人"; sendMessage(); } public void run() { try { while ((msg = br.readLine()) != null) { if (msg.trim().equals("bye")) { list.remove(socket); br.close(); pw.close(); msg = "【" + socket.getInetAddress() + "】离开聊天室!当前聊天室有【" + list.size() + "】人"; socket.close(); sendMessage(); break; } else { msg = "【" + socket.getInetAddress() + "】说:" + msg; sendMessage(); } } } catch (IOException e) { e.printStackTrace(); } } /** * 群发消息给聊天室的所有人 */ private void sendMessage() throws IOException { System.out.println(msg); for (Socket client : list) { pw = new PrintWriter(client.getOutputStream(), true); pw.println(msg); } } } } 聊天室客户端(输入bye可退出聊天室) package tf.thread; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ChatClient { private static final int PORT = 8888; private static ExecutorService exec = Executors.newCachedThreadPool(); public static void main(String[] args) throws Exception { new ChatClient(); } public ChatClient() { try { Socket socket = new Socket("192.168.1.120", PORT); exec.execute(new Sender(socket)); System.out .println("【" + socket.getInetAddress() + "】您好,欢迎来到阿飞聊天室!"); BufferedReader br = new BufferedReader(new InputStreamReader(socket .getInputStream())); String msg; while ((msg = br.readLine()) != null) { System.out.println(msg); } } catch (Exception e) { } } /** * 客户端线程获取控制台输入消息 */ static class Sender implements Runnable { private Socket socket; public Sender(Socket socket) { this.socket = socket; } public void run() { try { BufferedReader br = new BufferedReader(new InputStreamReader( System.in)); PrintWriter pw = new PrintWriter(socket.getOutputStream(), true); String msg; while (true) { msg = br.readLine(); pw.println(msg); if (msg.trim().equals("bye")) { pw.close(); br.close(); exec.shutdownNow(); break; } } } catch (Exception e) { e.printStackTrace(); } } } } 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2009-04-12
mina 几句就搞定了的
|
|
返回顶楼 | |
发表时间:2009-04-13
fjlyxx 写道 mina 几句就搞定了的 哈哈,实现功能的代码确实没多少,我只是加了一些进入聊天室提醒或离开聊天室提醒以及清除资源的代码,所以显得多了。见笑了! |
|
返回顶楼 | |
发表时间:2009-04-15
SOCKET 写一个聊天室也蛮有意思的!加油!
|
|
返回顶楼 | |
发表时间:2009-04-15
lvp 写道 SOCKET 写一个聊天室也蛮有意思的!加油! 是挺有意思的,看你写的聊天室,很不错呢 向你学习! |
|
返回顶楼 | |
发表时间:2009-04-15
LZ, private static List<Socket> list = new ArrayList<Socket>(); // 保存连接对象 服务器端有多个线程都会读list,貌似并非线程安全...
|
|
返回顶楼 | |
发表时间:2009-04-15
finux 写道 LZ, private static List<Socket> list = new ArrayList<Socket>(); // 保存连接对象 服务器端有多个线程都会读list,貌似并非线程安全...
恩,确实应该考虑同步问题,可以用 CopyOnWriteArrayList替换ArrayList |
|
返回顶楼 | |
发表时间:2009-04-16
呵呵,给你个建议.你可以这样写.当前一个线程拥有这个SOCKET,如果有请求那么这个拥有SOCKET的线程去现场池里面找一条可以用的线程并且把SOCKET给他,这样的话你就避免了线程的问题.如果要群发的话那么你应该考虑用消息通信机制,避免让消息去驱动连接.
|
|
返回顶楼 | |