实现Java简单的聊天室

所用主要知识:多线程+网络编程

效果如下图

/**

*

* @author Administrator

*

*简单的多人聊天系统——重点:同时性,异步性

*1、客户端:发送消息,并且接收消息

*1.1 消息发送至服务器:服务器每次都将客户发过来的信息发送到每个客户端

*1.2 接收消息:发送的同时也要接收消息,所以必须有两个线程,一个发送消息,一个接收消息

*1.3 关于这两个线程:如果没有线程,接收和发送就是按顺序执行的了,那么是发送后接收还是接收后发送?或者是

*一边可以发送一边又可以接收呢?答案不言而喻

*1.4 在客户端,用可以通过界面的点击按钮事件发送消息,所以就要开启一个线程来接收服务器发送给客户端的消息了

*1.5 多线程:不需按步骤逐步循环,可以和其他程序同时执行,不相互干扰

*2、服务器端:接收所有用户的消息并且借每个用户的消息发送给连接了服务器的客户端

*2.1服务器既要接收C端信息又要想所有C端发送信息,先收后发。一收就发。

*2.2S端还要显示C端上线提醒

*2.3上线提醒和收发信息是不影响的,互不干扰的,但是都要在S端上执行,如果没有线程,所以的程序都要按顺序执行了所以又要 多线程

*2.4一个线程负责向所以C端发送接收到的任何一条信息,一个线程负责显示C端上线的信息

*

*3、类:S端:Server、ServerFrame、sendThread 三个类

* C端:Client、ClientFrame 两个类

*

*/

1 packagecom.java.chat;2

3 importjava.awt.event.ActionEvent;4 importjava.awt.event.ActionListener;5 importjava.io.BufferedReader;6 importjava.io.BufferedWriter;7 importjava.io.IOException;8 importjava.io.InputStream;9 importjava.io.InputStreamReader;10 importjava.io.OutputStream;11 importjava.io.OutputStreamWriter;12 importjava.net.ServerSocket;13 importjava.net.Socket;14 importjava.util.ArrayList;15 importjava.util.List;16

17 importjavax.swing.JButton;18 importjavax.swing.JFrame;19 importjavax.swing.JTextArea;20

21

22 public classServer {23 //用于保存Socket的集合,也可以说是把个C端与S端的一个连接通道保存起来24 //作用:服务器将接收到的信息发给集合里的所以socket,也就是发给每个C端

25 public static List list = new ArrayList();26

27 public static voidmain(String[] args) {28 new ServerFrame("服务器端");29 }30

31 }32

33 /*

34 * 继承Jframe类表示该类可以创建一个窗口程序了,35 * 实现ActionListener:动作监听,在S端点击“启动服务器”是要执行的代码36 * 实现Runnable:实现多线程,该窗口是个客户端窗口,要开启一个线程接收显示服务器发过来的信息37 */

38 class ServerFrame extends JFrame implementsActionListener, Runnable {39

40 private static final long serialVersionUID = 1L;41

42 private ServerSocket serverSocket = null;43

44 privateSocket socket;45

46 privateJButton start;47 privateJTextArea message;48

49 publicServerFrame(String name) {50 super(name);51

52 start = new JButton("启动服务器");53 start.addActionListener(this);54 message = newJTextArea();55 message.setEditable(false);56 this.add(start, "North");57 this.add(message, "Center");58

59 this.setResizable(false);60 this.setBounds(0, 0, 400, 300);61 this.setVisible(true);62 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);63 }64

65 @Override66 public voidactionPerformed(ActionEvent e) {67 if (e.getSource() ==start) {68 //如果点击的按钮是开始按钮。则启动服务器。

69 try{70 serverSocket = new ServerSocket(6666);71 message.setText("服务器已启动。。。");72

73 //单击“启动服务器”开启一个线程用于获取用户上线的情况

74 new Thread(this).start();75

76 } catch(IOException e1) {77 e1.printStackTrace();78 }79 }80 }81

82 //获取C端上线的情况

83 @Override84 public voidrun() {85 String address = null;86 int port = 0;87 //用一个死循环一直让S端开启接收C端的连接,将C端的IP和端口显示在面板上88 //如果用循环的话就只能接收一次

89 while (true) {90 try{91 socket =serverSocket.accept();92 Server.list.add(socket);93 address =socket.getInetAddress().getHostAddress();94 port =socket.getPort();95 message.append("\r\nip/" + address + ":" + port + "\t上线了");96

97 //开启转发信息的线程

98 newsendThread(socket).start();99

100 } catch(IOException e) {101 //System.out.println(address + ":" + port + "\t退出了服务器");

102 }103 }104 }105

106 }107

108 /*

109 * 接收每个C端的信息并向每个C端发送接收到的信息110 */

111 class sendThread extendsThread {112 privateSocket socket;113

114 publicsendThread(Socket socket) {115 super();116 this.socket =socket;117 }118

119 @Override120 public voidrun() {121 InputStream is = null;122 BufferedReader br = null;123 String str = null;124 OutputStream os = null;125 BufferedWriter bw = null;126 while (true) {127 try{128 is =socket.getInputStream();129 br = new BufferedReader(newInputStreamReader(is));130 str =br.readLine();131 for(Socket s : Server.list) {132 os =s.getOutputStream();133 bw = new BufferedWriter(newOutputStreamWriter(os));134 bw.write(str);135 bw.newLine();136 bw.flush();137 }138 } catch(IOException e) {139 //如果断开连接则移除对于的socket

140 Server.list.remove(socket);141 }142 }143 }144 }

服务器端代码

1 packagecom.java.chat;2

3 importjava.awt.BorderLayout;4 importjava.awt.Color;5 importjava.awt.Font;6 importjava.awt.event.ActionEvent;7 importjava.awt.event.ActionListener;8 importjava.io.BufferedReader;9 importjava.io.BufferedWriter;10 importjava.io.IOException;11 importjava.io.InputStream;12 importjava.io.InputStreamReader;13 importjava.io.OutputStream;14 importjava.io.OutputStreamWriter;15 importjava.net.Socket;16 importjava.text.SimpleDateFormat;17 importjava.util.Date;18

19 importjavax.swing.JButton;20 importjavax.swing.JFrame;21 importjavax.swing.JLabel;22 importjavax.swing.JOptionPane;23 importjavax.swing.JPanel;24 importjavax.swing.JScrollPane;25 importjavax.swing.JTextArea;26 importjavax.swing.JTextField;27

28 /**

29 *30 *@authorAdministrator31 *32 */

33

34 public classClient {35 public static voidmain(String[] args) {36 new ClientFrame("客户端");37 }38 }39

40 /*

41 * 继承Jframe类表示该类可以创建一个窗口程序了,42 * 实现ActionListener:动作监听,就是一个事件发送后应该执行什么就要重新它的方法43 * 实现Runnable:实现多线程,该窗口是个客户端窗口,要开启一个线程接收显示服务器发过来的信息44 */

45 class ClientFrame extends JFrame implementsActionListener, Runnable {46

47 private static final long serialVersionUID = 1L;48

49 privateSocket socket;50 OutputStream os = null;51 BufferedWriter bw = null;52

53 JTextArea message;54 JScrollPane scroll;55 JTextField input;56 JButton submit;57 JPanel panel;58

59 String uname = "";60 //聊天页面

61 JPanel chat;62

63 //登录页面

64 JPanel login;65 JTextField username;66 JButton ok;67

68 publicClientFrame(String name) {69 super(name);70

71 message = newJTextArea();72 message.setEditable(false);73 scroll = newJScrollPane(message);74 input = new JTextField(20);75 submit = new JButton("发送");76 panel = newJPanel();77

78 panel.add(input);79 panel.add(submit);80 chat = new JPanel(newBorderLayout());81 chat.add(scroll, "Center");82 chat.add(panel, "South");83

84

85 //在创建客户端窗体是就要把客户端与服务端连接

86 try{87 //127.0.0.1表示本机地址,地址好端口都可以改,这要看服务器那边是什么地址和端口

88 socket = new Socket("127.0.0.1", 6666);89 os =socket.getOutputStream();90 bw = new BufferedWriter(newOutputStreamWriter(os));91

92 } catch(IOException e1) {93 e1.printStackTrace();94 }95

96 /*在创建C端窗体的时候也应该开启一个线程接收显示来自服务器的信息97 * 为什么要开启一个线程呢?因为在这个窗体里既要实现消息的发送,98 * 也要接收信息,而且两个不能按顺序进行,也互不干扰,所以开启一个线程时时刻刻等着S端发来的信息99 */

100 //接收信息

101 new Thread(this).start();102

103 //提交按钮工作监听器,点击提交时触发

104 submit.addActionListener(this);105

106 login = newJPanel();107 username = new JTextField(20);108 ok = new JButton("确定");109 ok.addActionListener(this);110 JLabel label = new JLabel("请输入用户名");111 label.setFont(new Font(Font.DIALOG, Font.BOLD, 28));112 label.setForeground(Color.red);113 login.add(label);114 login.add(username);115 login.add(ok);116

117 this.add(chat);118 this.add(login);119

120 this.setResizable(false);121 this.setBounds(400, 100, 400, 300);122 this.setVisible(true);123 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);124 }125

126 @Override127 public voidactionPerformed(ActionEvent e) {128 if (e.getSource() ==submit) {129 //如果点击提交按钮,则表示需要将信息发送出去。

130 String str = null;131 //以下三行是创建发送时间的代码

132 Date date = newDate();133 SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");134 String dateStr =format.format(date);135

136 str = uname+" "+dateStr+" "+input.getText();137

138 try{139 bw.write(str);140 bw.newLine();141 //System.out.println("客户端发送了:"+str);

142 bw.flush();143 } catch(IOException e1) {144 System.out.println("无法发送,服务器连接异常!");145 }146

147 //System.out.println(str);

148

149 } else if (e.getSource() == ok) {//用户登录

150 uname = username.getText();//获取文本框输入的文本信息

151 if ("".equals(uname)) {152 JOptionPane.showMessageDialog(this, "用户名不能为空!");153 } else{154 login.setVisible(false);155 chat.setVisible(true);156 this.setTitle(uname + " 的客户端");157 this.add(chat);158 }159 }160 }161

162 //run方法里面的是接受S端信息和将信息显示的代码

163 @Override164 public voidrun() {165 BufferedReader br = null;166 InputStream is = null;167 String str = null;168 try{169 is =socket.getInputStream();170 br = new BufferedReader(newInputStreamReader(is));171 while (true) {172 str = br.readLine()+"\r\n";173 message.append(str);174 }175 } catch(IOException e) {176 System.out.println("无法发送,服务器连接异常!");177 }178 }179

180 }

客户端代码

(完)

java 简单的聊天室_Java简单聊天室相关推荐

  1. java 语音聊天室_java语音聊天室原形的实现

    原本以为从 麦克风 上获得音频输入很复杂,原来javaSound已经封装的很简单了. 可以使用AudioCapture来完成. 聊天室音频的回放一般用流来完成:AudioPlayStream 类负责. ...

  2. java jsp中的日历表_JAVA简单的日历程序

    JAVA简单的日历程序 作者:未知    文章来源:www.jspcn.net 发布日期:2005年01月19日 /**以下是日历的代码程序 有疑问 回信 ycj@18e.net **/ //Cale ...

  3. java利用redis实现排行榜_Java简单使用redis-zset实现排行榜

    简单使用redis-zset实现排行榜 此方法实现一个根据某字段的查询次数进行排行,查询的次数越多排行越前(从大到小排序),适用于初学者 1.添加依赖 org.springframework.boot ...

  4. java中怎么引用圆周率_Java简单计算圆周率完整示例

    本文实例讲述了java简单计算圆周率.分享给大家供大家参考,具体如下: 这两天在网上看到一个题,已知pi可以用函数4 * (1 – 1/3 + 1/5 – 1/7 + -) 计算,计算出小数点后五位( ...

  5. java实现分页打印功能_Java简单高效实现分页功能

    今天想说的就是能够在我们操作数据库的时候更简单的更高效的实现,现成的crud接口直接调用,方便快捷,不用再写复杂的sql,带吗简单易懂,话不多说上方法 1.utils.java工具类中的方法 /** ...

  6. java类农夫过河问题_Java简单实现农夫过河问题示例

    本文实例讲述了Java简单实现农夫过河问题.分享给大家供大家参考,具体如下: 一.问题描述 老伯伯要带鱼.狗.猫过河到对岸.,有一条船,只能坐一个人,老伯每次只能带一样动物过河,当老伯不在的时侯狗会咬 ...

  7. java 简单的计算器程序_java 简单计算器

    做的很简陋  慢慢学习中!!!!!! import java.awt.*; public class 计算 { public static void main(String[] args) { win ...

  8. java 工厂模式的写法_java简单工厂模式是什么

    展开全部 所谓简单工厂模式, 就是将容易变化的地方, 考虑用一个独立Class来进行创造实体(Object)的过32313133353236313431303231363533e4b893e5b19e ...

  9. java飞机大战背景图片_Java简单飞机大战(1)

    在完成了多线程小球之后,就可以写一个飞机大战小游戏了,虽然比较简单,但玩起来还是有一点乐趣的.下面就讲一下我的大概思路和一些实现步骤. 一开始当然要想好一个框架,毕竟框架还是很重要的.当点击开始按钮的 ...

最新文章

  1. tcl把文本产生html,TCL脚本数据文件格式(译文)
  2. Python(21)--变量进阶
  3. 去哪儿-02-HeaderDev
  4. 属于attribute还是property。
  5. java并发初探ConcurrentHashMap
  6. nagios监控mysql主从
  7. 基本DNS服务器的配置
  8. LeetCode-1-two-sum
  9. 【疾病分类】基于matlab SVM植物叶子疾病检测和分类【含Matlab源码 093期】
  10. 阿里百度腾讯facebookMicrosoftGoogle开源项目汇总
  11. 红包算法-二倍均值法
  12. 啮齿类动物大尺度功能网络
  13. 2021年Wordpress博客装修美化(二)
  14. 解决CSS IOS字体自动调整放大了
  15. Go语言使用golang-jwt/jwt/v4进行JWT鉴权
  16. 《机器学习实战》学习笔记(八)
  17. 小议sns与web game
  18. element 日期选择器
  19. mysql登录密码特殊字符_MySQL用户密码中的特殊字符叹号(!)的妙用
  20. 数据分析方法01对比分析法

热门文章

  1. java 仿qq庅_iQQ-开源Java版qq客户端
  2. 无法加载文件 ,因为在此系统上禁止运行脚本
  3. 上蔡一高2021高考成绩查询,喜报!上蔡高考英雄榜出炉!
  4. ubuntu 20.04添加ubuntukylin源安装 应用的办法
  5. 早上第一杯别喝四种水
  6. 《物理学之美》读书摘记
  7. 前端面试题全面总结!
  8. 数字化经济能力:产品原型展示
  9. pads元件类型如何修改_在PADS里怎样修改PCB的元件编号
  10. python 小学生教材全解_小学生教材全解