一、控制台版本的群聊天室

                    其原理就是:通过死循环进行保存连接服务器的客户端,并创建一个容器来保存所有连接服务器的客户端             

服务器:

package com.zking.chat;import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Vector;/*** qq群的服务器* * @author Administrator*/
public class ServerChat {public static void main(String[] args) throws Exception {System.out.println("---------------------服务器--------------------");// 创建一个服务器ServerSocket ss = new ServerSocket(8989);// 无线去接收客户端的连接(需要使用一个容器去保存所有连接服务器的客户端)System.out.println("服务器已启动,端口号为8989");// 通过死循环进行保存连接服务器的客户端// 创建一个容器来保存所有连接服务器的客户端Vector<Socket> vc = new Vector<Socket>();Socket sk = null;while (true) {// 接收客户端sk = ss.accept();// 来一个System.out.println("某客户端上线了...");// 加一个到Vc中vc.add(sk);System.out.println("当前QQ群已加入新成员,目前有: " + vc.size());// 实例化无线读取全部客户端发送过来的消息new Thread(new ServerReadTread(vc, sk)).start();}// 关闭资源}}// 自定义线程类 无线接收已成功连接服务器的客户端发送的消息
class ServerReadTread implements Runnable {private Socket sk = null;private Vector<Socket> vc = null;public ServerReadTread(Vector<Socket> vc, Socket sk) {this.vc = vc;this.sk = sk;}@Overridepublic void run() {// 无线接收客户端的消息while (true) {// 输入流try {if (sk != null) {InputStream is = sk.getInputStream();InputStreamReader isr = new InputStreamReader(is);BufferedReader br = new BufferedReader(isr);String content = br.readLine();System.out.println("客户端说: " + content);// 问题:如何将content内容转发给QQ群中其他人。System.out.println("vc: " + vc.size());for (Socket socket : vc) {if (socket != null) {// 判断非空// 排除自己if (socket != sk) {// 输出流OutputStream os = socket.getOutputStream();OutputStreamWriter osw = new OutputStreamWriter(os);BufferedWriter bw = new BufferedWriter(osw);bw.write(content);bw.newLine();bw.flush();}}}}} catch (Exception e) {e.printStackTrace();}}}
}

客户端:

package com.zking.chat;import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Scanner;/*** 客户端的角色* * @author Administrator**/
public class ClientChat {public static void main(String[] args) throws Exception {System.out.println("---------------------客户端--------------------");// 连接服务器Socket sk = new Socket("127.0.0.1", 8989);System.out.println("连接成功");// 获取输出流 编写信息到网络中 让服务器去读取new Thread(new ClientChatThreadWriter(sk)).start();new Thread(new ClientChatThreadReader(sk)).start();}
}//无线写入
class ClientChatThreadWriter implements Runnable{Socket sk = null;public ClientChatThreadWriter(Socket sk) {this.sk = sk;}@Overridepublic void run() {Scanner sc = new Scanner(System.in);while(true) {try {OutputStream os = sk.getOutputStream();OutputStreamWriter osw = new OutputStreamWriter(os);BufferedWriter bw = new BufferedWriter(osw);System.out.println("请输入发送的内容");String content = sc.next();bw.write(content);bw.newLine();bw.flush();if("bye".equalsIgnoreCase(content)) {break;}} catch (Exception e) {// TODO: handle exception}}}
}//无限读取
class ClientChatThreadReader implements Runnable{Socket sk = null;public ClientChatThreadReader(Socket sk) {this.sk = sk;}@Overridepublic void run() {while(true) {try {InputStream is = sk.getInputStream();InputStreamReader isr = new InputStreamReader(is);BufferedReader br = new BufferedReader(isr);String content = br.readLine();System.out.println("某客户端说: "+content);} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
}

二、窗体版本的群聊天室 

           其原理就是:有一个客户发送消息,然后通过服务器保存消息发送给其他客户,然后其他的客户接收消息      

服务器:

package com.zking.files_09;import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
import java.util.Scanner;
import java.util.Vector;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;
import javax.swing.UIManager;public class MyServer extends JFrame {private ServerSocket ss = null;private Socket sk = null;private OutputStream os = null;private InputStream is = null;private InputStreamReader isr = null;private BufferedReader br = null;private OutputStreamWriter osw = null;private BufferedWriter bw = null;private Vector<Socket> vc = null;private JPanel jpa = new JPanel(null);private JLabel jla = new JLabel("服务器");private JLabel jlb = new JLabel("端 口");private JTextField jtfa = new JTextField(15);private JButton jba = new JButton("发送连接");private JTextArea jta = new JTextArea(20, 30);private JScrollPane jsp = new JScrollPane(jta);private JTextField jtfb = new JTextField(15);private JButton jbb = new JButton("发送");
//  private JButton jbc = new JButton("接收");public MyServer() {this.setTitle("");this.setSize(620, 620);this.setDefaultCloseOperation(3);this.setLocationRelativeTo(null);jla.setBounds(240, 0, 200, 100);jla.setFont(new Font("华文楷体", Font.BOLD, 45));jpa.add(jla);jlb.setBounds(50, 100, 60, 30);jlb.setFont(new Font("华文楷体", Font.BOLD, 20));jpa.add(jlb);jtfa.setBounds(130, 100, 250, 30);jtfa.setFont(new Font("华文楷体", Font.BOLD, 20));jpa.add(jtfa);jtfa.setText("9090");jba.setBounds(400, 100, 150, 30);jba.setFont(new Font("华文楷体", Font.BOLD, 20));jpa.add(jba);jta.setFont(new Font("华文隶书", Font.BOLD, 30));jsp.setBounds(10, 150, 590, 310);jsp.setFont(new Font("华文楷体", Font.BOLD, 30));jpa.add(jsp);jta.setEditable(false);jtfb.setBounds(70, 500, 250, 30);jtfb.setFont(new Font("华文楷体", Font.BOLD, 20));jpa.add(jtfb);jbb.setBounds(360, 500, 130, 30);jbb.setFont(new Font("华文楷体", Font.BOLD, 20));jpa.add(jbb);this.getContentPane().add(jpa);jba.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {int port = Integer.parseInt(jtfb.getText());jta.append("服务器正在打开!\n");// 端口号不能为1024之内(系统端口号或是保留端口号)也不能为1433(sqlserver端口号)if (port > 1024 && port != 1433) {try {// 创建服务器,将文本框中的内容获取并启动ss = new ServerSocket(port);// 创建一个集合拿到数据Vector<Socket> vc = new Vector<Socket>();System.out.println(vc);new Thread() {public void run() {while (true) {try {sk = ss.accept();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}try {Thread.sleep(100);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}vc.add(sk);jta.append("与客户端连接成功!\n");jtfb.setEnabled(false);jta.append("有客户端连接:" + sk.getInetAddress().getHostName() + "\n");new ServerThread0(vc,sk).start();}};}.start();} catch (Exception e2) {// e2.printStackTrace();}} else {JOptionPane.showMessageDialog(null, "端口号不能为1024之内(系统端口号或是保留端口号)也不能为1433(sqlserver端口号)");}}});jbb.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {try {OutputStream os = sk.getOutputStream();OutputStreamWriter osw = new OutputStreamWriter(os);BufferedWriter bw = new BufferedWriter(osw);bw.write(jtfb.getText());bw.newLine();bw.flush();} catch (Exception e1) {e1.printStackTrace();}jta.append("自己\t"+jtfb.getText()+"\n");jtfb.setText("");}});class ServerReadTread implements Runnable {private Socket sk = null;private Vector<Socket> vc = null;public ServerReadTread(Vector<Socket> vc, Socket sk) {this.vc = vc;this.sk = sk;}@Overridepublic void run() {// 无线接收客户端的消息while (true) {// 输入流try {String text = jtfb.getText();if (sk != null) {is = sk.getInputStream();isr = new InputStreamReader(is);br = new BufferedReader(isr);for (Socket socket : vc) {if (socket != null) {// 判断非空// 排除自己if (socket != sk) {// 输出流OutputStream os = socket.getOutputStream();OutputStreamWriter osw = new OutputStreamWriter(os);BufferedWriter bw = new BufferedWriter(osw);bw.write(text);bw.newLine();bw.flush();jta.append("我:" + text + "\n");}}}}} catch (Exception e) {e.printStackTrace();}}}}this.setVisible(true);}public static void main(String[] args) {try {UIManager.setLookAndFeel("com.jtattoo.plaf.mcwin.McWinLookAndFeel");} catch (Exception e) {e.printStackTrace();}new MyServer();}}class ServerThread0 extends Thread{//套接字
private Socket sk =null;
//数组
private Vector<Socket> vc =null;
/*** 构造方法进行赋值* @param sk 套接字* @param vc 数组*/
public ServerThread0(Vector<Socket> vc,Socket sk) {this.vc = vc;this.sk = sk;
}
@Override
public void run() {while(true) {try {//获取消息InputStream is = sk.getInputStream();InputStreamReader isr = new InputStreamReader(is);BufferedReader br = new BufferedReader(isr);//读取一整行String r=br.readLine()+"/"+sk.getInetAddress().getHostName();//把当前电脑名字用/分割开发送到网络for (Socket s : vc) {//不能没有对象发送if(s!=null) {//不能发送给自己if(s!=sk) {//发送消息OutputStream os = s.getOutputStream();OutputStreamWriter osw =new OutputStreamWriter(os);BufferedWriter bw =new BufferedWriter(osw);//把服务器获取到的客户端内容写入返回给另一个客户端bw.write(r);bw.newLine();bw.flush();}}}
//          //通过条件进行自我关闭
//          if("bye".equals(r)) {
//              //清除数据
//              vc.remove(0);
//              //进行结束
//              break;
//          }} catch (Exception e) {//系统处理异常
//          e.printStackTrace();}}
}
}

客户端:

package com.zking.files_09;import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Date;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;
import javax.swing.UIManager;public class MyClinet extends JFrame {private Socket sk = null;private OutputStream os = null;private InputStream is = null;private InputStreamReader isr = null;private BufferedReader br = null;private OutputStreamWriter osw = null;private BufferedWriter bw = null;private JPanel jpa = new JPanel(null);private JLabel jla = new JLabel("客户端");private JLabel jlb = new JLabel("IP:");private JTextField jtfa = new JTextField(15);private JLabel jlc = new JLabel("端口:");private JTextField jtfb = new JTextField(15);private JButton jba = new JButton("连接");private JTextArea jta = new JTextArea(20, 30);private JScrollPane jsp = new JScrollPane(jta);private JTextField jtfc = new JTextField(15);private JButton jbb = new JButton("发送");public MyClinet() {this.setTitle("");this.setSize(620, 620);this.setDefaultCloseOperation(3);this.setLocationRelativeTo(null);jla.setBounds(240, 0, 200, 100);jla.setFont(new Font("华文楷体", Font.BOLD, 45));jpa.add(jla);jlb.setBounds(50, 100, 100, 30);jlb.setFont(new Font("华文楷体", Font.BOLD, 15));jpa.add(jlb);jtfa.setBounds(90, 100, 150, 30);jtfa.setFont(new Font("华文楷体", Font.BOLD, 20));jpa.add(jtfa);jtfa.setText("127.0.0.1");jlc.setBounds(260, 100, 60, 30);jlc.setFont(new Font("华文楷体", Font.BOLD, 15));jpa.add(jlc);jtfb.setBounds(310, 100, 150, 30);jtfb.setFont(new Font("华文楷体", Font.BOLD, 20));jpa.add(jtfb);jba.setBounds(480, 100, 100, 30);jba.setFont(new Font("华文楷体", Font.BOLD, 20));jpa.add(jba);jta.setFont(new Font("华文隶书", Font.BOLD, 30));jsp.setBounds(10, 150, 590, 310);jsp.setFont(new Font("华文楷体", Font.BOLD, 30));jpa.add(jsp);jta.setEditable(false);jtfc.setBounds(70, 500, 250, 30);jtfc.setFont(new Font("华文楷体", Font.BOLD, 20));jpa.add(jtfc);jbb.setBounds(360, 500, 130, 30);jbb.setFont(new Font("华文楷体", Font.BOLD, 20));jpa.add(jbb);this.getContentPane().add(jpa);jba.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {jta.append("客户端正在连接...\n");String address = jtfa.getText();int port = Integer.parseInt(jtfb.getText());if(port>1024 && port!=1433) {try {sk = new Socket(address, port);jtfa.setEnabled(false);jtfb.setEnabled(false);} catch (Exception e2) {}if(sk!=null) {jba.setEnabled(false);}else {JOptionPane.showMessageDialog(null, "未连接上!");}}else {JOptionPane.showMessageDialog(null, "端口号不能为1024之内(系统端口号或是保留端口号)也不能为1433(sqlserver端口号)");}//创建一个人来无限等待消息new Thread() {public void run() {while(true) {try { InputStream is = sk.getInputStream();InputStreamReader isr =new InputStreamReader(is);BufferedReader br =new BufferedReader(isr);String s =br.readLine();//读取网络发送的消息String name =s.substring(s.lastIndexOf("/")+1);String read =s.substring(0,s.lastIndexOf("/"));jta.append("\t\t"+name+"\t\t"+read+"\n");} catch (Exception e) {e.printStackTrace();}    }};}.start();}});jbb.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {String text = jtfc.getText();if (sk != null) {try {// 获取界面连接os = sk.getOutputStream();// 字节流osw = new OutputStreamWriter(os);// 字符流FileWriter 缓冲流bw = new BufferedWriter(osw);bw.write(text);bw.newLine();bw.flush();jta.append("我:" + text + "\n");} catch (Exception e2) {//e2.printStackTrace();}} else {JOptionPane.showMessageDialog(null, "请先获取连接....");}}});this.setVisible(true);}public static void main(String[] args) {try {UIManager.setLookAndFeel("com.jtattoo.plaf.mcwin.McWinLookAndFeel");} catch (Exception e) {//e.printStackTrace();}new MyClinet();}}

个人总结:

 群聊天室简单来说就是:一个服务器多个客户端,服务器负责接收客户端发送的消息,再将接收到的消息发送给除发送消息以外的所有客户端。

高级API快速入门之群聊天室【09】相关推荐

  1. 高级API 快速入门之第六章 用窗体实现Socket对话聊天案例

    服务端: package com.zking.test;import java.awt.Font; import java.awt.event.ActionEvent; import java.awt ...

  2. 高级API 快速入门之第七章 本地模拟下载文件

    一:控制台版本的聊天互发消息     服务端: package com.zking.test;import java.io.BufferedReader; import java.io.Buffere ...

  3. websocket以及nodejs联手打造的类qq群聊天室 教程 附 原代码

    这次给大家分享的是我自己开发的多人聊天室,利用websocket 以及服务器端使用node.js 来让用户不需要刷新浏览器就可以获得实时更新. 如下面图所示的样子.开发出类QQ群聊天室的主界面,当然U ...

  4. Keras functional API快速入门

    2019独角兽企业重金招聘Python工程师标准>>> Keras functional API快速入门 The Keras functional API is the way to ...

  5. php yii2 api框架,Yii2框架制作RESTful风格的API快速入门教程

    先给大家说下什么是REST restful REST全称是Representational State Transfer,中文意思是表述(编者注:通常译为表征)性状态转移. 它首次出现在2000年Ro ...

  6. qq位置如何用启动百度地图定位服务器,腾讯位置服务API快速入门

    前言 之前项目有个需求,在网页上显示微信发送过来的位置信息,该开始想用百度地图,后来发现腾讯地图相对简单一点 快速入门 申请Key 引入js 把###替换成你申请的key 定义容器 设置好宽高度 设置 ...

  7. Pandas高级数据分析快速入门之三——数据挖掘与统计分析篇

    Pandas高级数据分析快速入门之一--Python开发环境篇 Pandas高级数据分析快速入门之二--基础篇 Pandas高级数据分析快速入门之三--数据挖掘与统计分析篇 Pandas高级数据分析快 ...

  8. python学习之使用UDP和多线程实现一个群聊天室

    在学习UDP的时候,想着试一试能不能搞一个命令窗口的udp聊天工具,因为udp的广播机制,所以就想着干脆直接搞一个群聊的吧.不过最后搞来搞去,命令窗口下使用多线程,没有做出什么好看整洁的"图 ...

  9. Python实现群聊天室(基于TCP)

    一.服务端代码: 1. 需要socket,threading 这两个模块 2.使用单进程多线程实现: 1)多个客户端同时在线群聊 2)新客户端上线广播通知其他在线客户端 3)在线客户端下线广播通知其他 ...

最新文章

  1. 开发者和矿工合二为一将是比特币世界的灾难
  2. grunt live reload 配置记录
  3. 2020 中国技术力量年度榜单
  4. 在线html5 api中文版,HTML5+ API Reference
  5. HTMl文件的阶层架构 访问父元素和子元素
  6. 应用程序初次运行数据库配置小程序(Java版)
  7. Hive Hooks介绍
  8. 1月4日 每次安装都有新问题
  9. Linux运维之道(大量经典案例、问题分析,运维案头书,红帽推荐)
  10. macOS装机必备(软件测试人员)
  11. 放大电路的分析方法详解
  12. 汇编语言下载安装及使用(hello world,仅供学习参考)
  13. SOME/IP报文格式-Payload
  14. 微信小程序超市购物+后台管理系统|前后分离VUE
  15. 生活就像一盒巧克力,你永远不知道会尝到哪种滋味
  16. 9.4 多元复合函数求导
  17. NYOJ - 595
  18. 微信支付二维码上添加logo
  19. 如何抠图人像换背景?教你一个在线操作的方法
  20. 数据结构——课程设计之~安排教学计划

热门文章

  1. 吉林大学应用数学(学硕)专业考研上岸经验分享
  2. 星球前线 | Libra最大的竞争对手是什么?Calibra高管给出答案
  3. 一次重新的认识--第二次随笔
  4. 【免费开放源码】审批类小程序项目实战(活动申请页面)
  5. Install DBeaver in Mac
  6. 唱好歌首先要掌握上海学唱歌的发音技巧
  7. 互联网日报 | 贝壳找房更新IPO招股书;云闪付App用户数突破3亿;宝马近11年来首次季度亏损...
  8. java调用MySQL数据库
  9. Java 访问MySQL的小例子
  10. 国内外语音识别行业最全盘点及技术分析和预测