chatroom

chatroomchatroomchatroom
chatRoom.zip 聊天室聊天室服务端 package chatroom; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Socket; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashSet; import javax.swing.JFrame; import javax.swing.JOptionPane; /** * 聊天室服务器端 ChatRoomServer类 * * @version 1.01, 09/04/10 */ public class ChatRoomServer { private ServerSocket ss; /* 存放Socket的集合hs */ private HashSet<Socket> hs; public ChatRoomServer() { JFrame jf = new JFrame(); do { /* * 弹出输入对话框,提示输入服务器需要绑定的端口号 */ int port = Integer.parseInt(JOptionPane.showInputDialog(jf, "bind port:")); try { ss = new ServerSocket(port); System.out.println("server start success,now listening port:" + port); } catch (Exception e) { /* 弹出确认框进行确认 */ int op = JOptionPane.showConfirmDialog(jf, // 指定是在jf中弹出确认框 "bind fail,retry?", // 框体内容 "bind fail", // 对话框的标题 JOptionPane.YES_NO_OPTION); // 确认框按钮项 /* 如果选择'否',则退出程序 */ if (op == JOptionPane.NO_OPTION) { System.exit(1); } /* 打印异常栈信息 */ e.printStackTrace(); } } while (ss == null); /* 创建HashSet,用来存放Socket对象 */ hs = new HashSet<Socket>(); while (true) { try { /* 获得Socket,网络阻塞,等待客户端的连接 */ Socket s = ss.accept(); /* 一旦客户端连接上,则加入HashSet,便于维护 */ hs.add(s); /* 启动一个服务线程,为客户端服务 */ new ServerThread(s).start(); } catch (IOException e) { e.printStackTrace(); } } } /** * 成员内部类,服务线程类 */ class ServerThread extends Thread { private Socket s; public ServerThread(Socket s) { this.s = s; } @Override public void run() { BufferedReader br = null; try { br = new BufferedReader(new InputStreamReader(s .getInputStream())); while (true) { /* 从网络中读取客户端发出的消息 */ String str = br.readLine(); /* * 客户退出时的处理逻辑 规则:以"%EXIT_CHATROOM%"开头的消息为客户退出标记 */ if (str.charAt(0) == '%') { String com = str.split("%")[1]; if (com.equals("EXIT_CHATROOM")) { hs.remove(s); printMessage(str.split("%")[2] + ",leave!"); s.close(); break; } } else { /* 正常情况,直接向客户端群发消息 */ printMessage(str); } } } catch (IOException e) { e.printStackTrace(); } } /* * 负责为客户端群发消息 */ private void printMessage(String mes) { System.out.println(mes); try { /* 遍历所有Socket */ for (Socket s : hs) { PrintStream ps = new PrintStream(s.getOutputStream()); /* 产生发消息的时刻 */ Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss"); /* 向客户端发消息,消息结构为mes [yyyy-MM-dd HH:mm:ss] */ ps.println(mes + " [" + sdf.format(date) + "]"); /* 注意需要及时flush,清空缓冲区 */ ps.flush(); } } catch (IOException e) { e.printStackTrace(); } } } /* * 主方法,启动聊天室服务器端 */ public static void main(String[] args) { new ChatRoomServer(); } } 客户端窗体 package chatroom; import java.awt.BorderLayout; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.Socket; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; /** * 客户端窗口ChatRoomClientFrame类 负责客户端的视图表示、事件处理等逻辑 作为一个窗口,所以本类继承自JFrame * 为了实现事件处理,本类实现了ActionListener接口 * * @version 1.01, 09/04/10 */ public class ChatRoomClientFrame extends JFrame implements ActionListener { private static final long serialVersionUID = 3484437496861281646L; private JTextArea jta; // 多行文本域 private JLabel label; // 文本标签 private JTextField jtf; // 单行文本框 private JButton jb; // 按钮 private Socket socket; // socket 套接字 private String name; // 用户名 /* * ChatRoomClientFrame构造方法,负责初始化以及添加事件处理 */ public ChatRoomClientFrame(String name, Socket socket) { super("chatroom"); Font f = new Font("楷体", Font.BOLD, 20); /* 设置字体 */ jta = new JTextArea(10, 10); /* 创建10行10列的空多行文本域 */ jta.setEditable(false); /* 设置多行文本域为不可编辑 */ jta.setFont(f); /* 设置多行文本域字体 */ label = new JLabel(name + ":"); /* 创建带有用户名的文本标签 */ label.setFont(f); /* 设置文本标签字体 */ jtf = new JTextField(25); /* 创建单行文本框 */ jtf.setFont(f); /* 设置单行文本框字体 */ jb = new JButton("send"); /* 创建按钮 */ this.name = name; this.socket = socket; init(); /* 初始化,设置组件关系 */ addEventHandler(); /* 为组件添加事件监听 */ } /* * 初始化组件关系方法,供构造方法调用 */ private void init() { JScrollPane jsp = new JScrollPane(jta); this.add(jsp, BorderLayout.CENTER); JPanel jp = new JPanel(); jp.add(label); jp.add(jtf); jp.add(jb); this.add(jp, BorderLayout.SOUTH); } /* * 负责为各组件添加事件处理机制 */ private void addEventHandler() { jb.addActionListener(this); // 为jb添加事件监听,JButton点击触发事件 jtf.addActionListener(this); // 为jtf添加事件监听,JTextField敲回车触发事件 /* 设置JFrame默认关闭状态:DO_NOTHING_ON_CLOSE */ this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); /* 为JFrame添加窗口事件监听 */ this.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent arg0) { /* 弹出确认框进行交互 */ int op = JOptionPane.showConfirmDialog( ChatRoomClientFrame.this, "exit?", "exit", JOptionPane.YES_NO_OPTION); if (op == JOptionPane.YES_OPTION) { try { PrintStream ps = new PrintStream(socket .getOutputStream()); /* 向服务器发送以%EXIT_CHATROOM%name为格式的串,代表退出信号 */ ps.println("%EXIT_CHATROOM%" + name); /* 注意需要及时flush */ ps.flush(); try { Thread.sleep(168); // 进行延时控制,防止提前关闭socket } catch (InterruptedException e) { e.printStackTrace(); } socket.close(); // 关闭客户端socket ps.close(); // 关闭流 } catch (IOException e) { e.printStackTrace(); } System.exit(1); // 退出程序 } } }); } /* * 实现事件处理方法 */ public void actionPerformed(ActionEvent ae) { try { PrintStream ps = new PrintStream(socket.getOutputStream()); ps.println(name + ": " + jtf.getText()); ps.flush(); /* 清空jtf中内容 */ jtf.setText(""); } catch (IOException e) { e.printStackTrace(); } } /* * 显示并执行窗口逻辑 */ public void showMe() { this.pack(); // 自动调整此窗口的大小 this.setVisible(true); // 设置窗口可见 /* * 启动线程,负责接收服务器端发来的消息 */ new Thread() { @Override public void run() { BufferedReader br = null; try { br = new BufferedReader(new InputStreamReader(socket .getInputStream())); while (true) { /* 从网络中读取服务器发出的数据 */ String str = br.readLine(); /* 对JTextArea进行追加消息 */ jta.append(str + "\n"); } } catch (IOException e) { e.printStackTrace(); } } }.start(); } } 客户端 package chatroom; import java.io.PrintStream; import java.net.Socket; import javax.swing.JFrame; import javax.swing.JOptionPane; /** * 聊天室客户端 ChatRoomClient * * @version 1.01, 09/04/10 */ public class ChatRoomClient { private String name; // 用户名 private Socket socket; // Socket 套接字 private ChatRoomClientFrame frame; // 组合复用 ChatRoomClientFrame /* * ChatRoomClient构造方法,负责构造客户端表示逻辑 */ public ChatRoomClient() { JFrame jf = new JFrame(); /* * 弹出用户输入对话框,提示用户输入服务器的IP地址 返回相应字符串形式,存于变量serverIP,缺省值127.0.0.1 */ String serverIP = JOptionPane.showInputDialog(jf, "server IP:", "127.0.0.1"); /* * 弹出用户输入对话框,提示用户输入服务器端口号 转化为int形式返回,存于变量serverPort */ int serverPort = Integer.parseInt(JOptionPane.showInputDialog(jf, "port:")); /* * 弹出用户输入对话框,提示用户输入用户名,存于成员属性name */ name = JOptionPane.showInputDialog(jf, "your name:"); try { /* 通过IP和Port,与服务器端建立连接 */ socket = new Socket(serverIP, serverPort); /* 给服务器发消息 */ PrintStream ps = new PrintStream(socket.getOutputStream()); ps.println(name + ",login !"); } catch (Exception e) { JOptionPane.showMessageDialog(jf, "fail,check the connection!"); e.printStackTrace(); System.exit(1); } /* * 创建ChatRoomClientFrame,进行客户端主窗口的显示 */ frame = new ChatRoomClientFrame(name, socket); frame.showMe(); } /* * 主方法,启动聊天室客户端 */ public static void main(String[] args) { new ChatRoomClient(); } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值