仿QQ多人聊天室

下载地址:链接:https://pan.baidu.com/s/1dLFjSxwTA4gL5lI0B4UGuQ 
提取码:2qs0

有两个项目,分别是服务器chatterServer和客户端chatter,先开启服务器,再开启客户端,默认8888端口。

先上图(回环测试,即自己和自己聊天):

实现的主要功能:

1、一对一聊天:连接到服务器的所有客户端和另一个客户端“一对一”聊天

2、多对多聊天:连接到服务器的所有客户端在同一聊天室内聊天

使用到的Java技术:

1、Java图形界面编程(JFrame和各种组件的使用)。还包括内部类,事件监听。

2、Java IO。主要是字节流,聊天信息通过字节流编码并发送、接收。

3、Java TCP通信。

4、Java多线程。

5、Java集合。其中一个重点是重写equals方法和hashCode方法

6、Java异常处理

代码结构:

客户端

代码分为4个包:

com.chatter.GUI 和图形界面相关的类,主要是GUI类
com.chatter.client 和客户端后台有关的类,主要是Client类
com.chatter.user 和用户信息存储有关的类,包含Message类(数据的打包和解包),User类(用户信息,最后没用),PersonRecord类(用于记录和某个特定客户端的聊天记录),Record类(用于记录用户和每个其他用户的聊天记录)
com.chatter.main main方法

项目类图(客户端):

服务器只有一个类,和从客户端复制过去的一些类

主要代码如下:

UI模块:

package com.chatter.gui;import java.awt.*;
import java.awt.event.*;
import java.util.Collection;
import java.util.HashSet;import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;import com.chatter.client.Client;
import com.chatter.user.Message;
import com.chatter.user.PersonRecord;
import com.chatter.user.User;public class GUI {Client client;JFrame frame;Container pane;JPanel window, up, left, center, down;//上方的软件名private JLabel label;//左侧选择聊天对象的列表JList<String> list;DefaultListModel<String> dlm;//中间的聊天消息显示JTextArea text;//下方输入文本的区域public JTextField words;//发送按钮JButton button;final int WINDOW_WIDTH = 480;final int WINDOW_HEIGHT = 640;final double CUT_RATE_LEFT = 0.30;public GUI() {frame = new JFrame();pane = frame.getContentPane();window = new JPanel(new BorderLayout());up = new UpperPanel();left = new JPanel();center = new JPanel();down = new JPanel(new BorderLayout());//上方的软件图标和名称label = new JLabel();label.setPreferredSize(new Dimension(150,50));label.setFont(new Font("楷体", Font.PLAIN, 30));label.setText("GG聊天室");up.add(label);pane.add(BorderLayout.NORTH, up);//左侧的聊天对象选择栏dlm = new DefaultListModel<String>();list = new JList<String>(dlm);list.setPreferredSize(new Dimension((int)(CUT_RATE_LEFT*WINDOW_WIDTH), 400));list.setModel(dlm);dlm.clear();dlm.addElement("0000000000008888");list.setSelectedIndex(0);list.addListSelectionListener((ListSelectionListener) new ListListener());;left.add(list);pane.add(BorderLayout.WEST, left);//中心的聊天消息显示text = new JTextArea();//text.setPreferredSize(new Dimension(280,2000));text.setEditable(true);text.setLineWrap(true);JScrollPane scrollpane1 = new JScrollPane(text);scrollpane1.setPreferredSize(new Dimension(300, 400));scrollpane1.createVerticalScrollBar().setVisible(false);scrollpane1.createHorizontalScrollBar().setVisible(true);center.add(scrollpane1);pane.add(BorderLayout.CENTER, center);//下方的聊天内容输入words = new JTextField();//words.setText("你好,我已经加你为好友\n,我们可以开始聊天了");words.setEditable(true);//words.setLineWrap(true);//words.setWrapStyleWord(true);JScrollPane scrollpane2= new JScrollPane(words);scrollpane2.setPreferredSize(new Dimension(350, 100));scrollpane2.createVerticalScrollBar().setVisible(false);scrollpane2.createHorizontalScrollBar().setVisible(true);//scrollpane2.setAutoscrolls(true);down.add(BorderLayout.WEST, scrollpane2);//发送按钮button = new JButton("发送");BottonListener bl = new BottonListener();//bl.setTextField(words);button.addActionListener(bl);button.setPreferredSize(new Dimension(100, 30));down.add(BorderLayout.EAST, button);pane.add(BorderLayout.SOUTH, down);frame.setSize(WINDOW_WIDTH, WINDOW_HEIGHT);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setVisible(true);}public void receive(Message msg) {System.out.println("收到消息,准备更新. msg Type: " + msg.getHead());if (msg.getHead() == 1) {String[] s = msg.getContent().split("[|]");Collection<PersonRecord> tmp_c = new HashSet<PersonRecord>();for(String str:s) {tmp_c.add(new PersonRecord(Long.parseLong(str)));System.out.println(str);}tmp_c.add(new PersonRecord(8888));System.out.println("新建列表内容");for (Object o:tmp_c.toArray()) {System.out.println(((PersonRecord)o).personId);}System.out.println("_______ENC");client.record.c.addAll(tmp_c);client.record.c.retainAll(tmp_c);System.out.println("加入后原列表内容");for (Object o:client.record.c.toArray()) {System.out.println(((PersonRecord)o).personId);}System.out.println("_______ENC2");//System.out.println("系统原有集合:"+(PersonRecord[])(client.record.c.toArray()));//System.out.println("新创建集合:"+ (PersonRecord[])(tmp_c.toArray()));for(PersonRecord pr: client.record.c) {if (dlm.contains(String.format("%016d" ,pr.personId)) == false)dlm.addElement(String.format("%016d" ,pr.personId));}}else if (msg.getHead() == 0)for(PersonRecord pr:client.record.c) {if(pr.personId == msg.getTransmitter())pr.chatRecord.append("对方:");pr.chatRecord.append(msg.getContent());pr.chatRecord.append("\n");text.setText(pr.chatRecord.toString());}else if (msg.getHead() == 99) {for(PersonRecord pr:client.record.c) {pr.chatRecord.append("对方:");pr.chatRecord.append(msg.getContent());pr.chatRecord.append("\n");text.setText(pr.chatRecord.toString());}}}public void send(String content) {System.out.println("正在发送给"+list.getSelectedValue()+" 内容:" + content);Message m = new Message();content.replaceAll("\\n", "");m.setContent(content);//0:普通消息if (Long.parseLong(list.getSelectedValue()) == 8888) {m.setHead(99);m.setReceiver(Long.parseLong(list.getSelectedValue()));}else {m.setHead(0);m.setReceiver(Long.parseLong(list.getSelectedValue()));}System.out.println("发送与接收者:" +m.getTransmitter() +" "+m.getReceiver());for(PersonRecord pr:client.record.c) {System.out.println("现有用户id:"+pr.personId);if(pr.personId == m.getReceiver()) {System.out.println("正在添加聊天记录");pr.chatRecord.append("你:");pr.chatRecord.append(m.getContent());pr.chatRecord.append("\n");text.setText(pr.chatRecord.toString());}}System.out.println("-------ready to send msg--------");client.send(m);}class BottonListener implements ActionListener{public void actionPerformed(ActionEvent e) {String str = words.getText();if(str.trim().length() == 0) return;words.setText("");send(str);} }class ListListener implements ListSelectionListener{public void actionPerformed(ActionEvent e) {}public void valueChanged(ListSelectionEvent e) {for(PersonRecord pr:client.record.c) {if(pr.personId == Long.parseLong(list.getSelectedValue()))text.setText(pr.chatRecord.toString());}}}public void setClient(Client c) {this.client = c;}
}

客户端后台Client:

package com.chatter.client;import java.io.*;
import java.io.IOException;
import java.net.*;import com.chatter.gui.GUI;
import com.chatter.user.Message;
import com.chatter.user.PersonRecord;
import com.chatter.user.Record;public class Client {private String ip;private int port;private long localId;private Socket socket;private PrintWriter pw;private BufferedReader br;private GUI gui;public Record record;public Client(String ip, int port) {this.ip = ip;this.port = port;try {socket = new Socket(ip, port);OutputStream os = socket.getOutputStream();OutputStreamWriter osw = new OutputStreamWriter(os, "utf-8");BufferedWriter bw = new BufferedWriter(osw);pw = new PrintWriter(bw, true);InputStream is = socket.getInputStream();InputStreamReader isr = new InputStreamReader(is, "utf-8");br = new BufferedReader(isr);localId = getLocalId(ip, port); record = new Record();//record.c.add(new PersonRecord(8888));}catch (Exception e) {System.out.println("连接服务器失败");System.exit(0);}}public boolean setGUI(GUI g) {if (g == null)return false;this.gui = g;return true;}public void start() {Thread t_receive = new Thread() {String line;public void run() {try {while((line = br.readLine()) != null) {try {System.out.print("收到新消息");System.out.println("\t" + line);Message msg = new Message(line);System.out.println("Before calling gui.receive: ");System.out.println(msg.getContent());gui.receive(msg);}catch(Exception e) {e.printStackTrace();System.out.println("Message encoding error");}}} catch (Exception e) {e.printStackTrace();System.out.println("服务器主动断开连接。");System.exit(0);}}};t_receive.start();}static public long getLocalId(String IP, int port) {String[] ipSplit = IP.split("\\.");long[] arr = new long[5];for (int i=0; i<ipSplit.length; i++) {arr[i] = Integer.parseInt(ipSplit[i]);}arr[4] = port;return arr[4]+arr[3]*10000+arr[2]*10000000+arr[1]*1000000000L+arr[0]*10000000000000L;}public void send(Message msg) {if (msg.getHead() == 0) {System.out.println("Sending message to server...");msg.setTransmitter(localId);String str = msg.toString();System.out.println("\tmessage content: "+msg.getContent());pw.println(str);}else if (msg.getHead() == 99) {msg.setTransmitter(localId);}}public void setRecord(Record r) {this.record = r;record.c.add(new PersonRecord(8888));}}

服务器Server:

package com.chatter.server;import java.io.*;
import java.net.*;
import java.util.Collection;
import java.util.HashSet;import com.chatter.user.Message;
import com.chatter.user.User;public class Server {ServerSocket serverSocket;Collection<User> c = new HashSet<User>();public Server() {try {serverSocket = new ServerSocket(8888);while(true) {Socket socket = serverSocket.accept();long remoteID = getIDFromIP(socket.getInetAddress().getHostAddress());System.out.println(socket.getInetAddress() + "已连接");Thread thread = new Thread() {public void run() {try {OutputStream os = socket.getOutputStream();OutputStreamWriter osw = new OutputStreamWriter(os, "utf-8");BufferedWriter bw = new BufferedWriter(osw);PrintWriter pw = new PrintWriter(osw, true);InputStream is = socket.getInputStream();InputStreamReader isr = new InputStreamReader(is, "utf-8");BufferedReader br = new BufferedReader(isr);User u = new User(socket, getIDFromIP(socket.getInetAddress().getHostAddress()), br, pw);c.add(u);System.out.println(u.id + "已连接");sendUpdateMsg();//System.exit(0);String line;while((line = br.readLine()) != null) {Message msg = new Message(line);System.out.println("服务器收到消息: " + msg.toString());if (msg.getHead() == 0) {long id = msg.getReceiver();System.out.println("Receiver from raw msg: "+msg.getReceiver());//id = id*10000+8888;System.out.println("Sending to Client: "+id);for (User tmp: c) {System.out.println("服务器现有用户: "+tmp.id);if (tmp.id == id) {System.out.println("Sending to Client: "+tmp.socket.getInetAddress());tmp.pw.println(msg.toString());pw.flush();}}}else if (msg.getHead() == 99) {for (User tmp: c) {tmp.pw.println(msg.toString());}}} }catch(Exception e) {for (User u: c) {if (u.id == remoteID) {c.remove(u);sendUpdateMsg();}}e.printStackTrace();;}}                   };thread.start();}} catch (Exception e) {e.printStackTrace();System.out.println("服务器开启失败");System.exit(0);}}private void sendUpdateMsg() {System.out.println("发送在线列表更新信息中...");Message msg = new Message();msg.setHead(1);msg.setTransmitter(0);StringBuffer s = new StringBuffer();for (User tmp:c) {s.append(String.format("%016d", tmp.id));s.append('|');}msg.setContent(s.toString());for (User tmp:c) {System.out.println("Sending to "+tmp.id);msg.setReceiver(tmp.id);tmp.pw.println(msg.toString());}}private long getIDFromIP(String IP) {try {String[] ipSplit = IP.split("\\.");long[] arr = new long[5];for (int i=0; i<ipSplit.length; i++) {arr[i] = Integer.parseInt(ipSplit[i]);}arr[4] = 8888;return arr[4]+arr[3]*10000+arr[2]*10000000+arr[1]*1000000000L+arr[0]*10000000000000L;}catch(Exception e) {e.printStackTrace();}return 0;}
}

个人作品,请勿转载。

【Java课程设计】仿QQ多人聊天室(基于TCP协议与JavaSwing)附下载相关推荐

  1. node php聊天室,利用socket.io实现多人聊天室(基于Nodejs)

    利用socket.io实现多人聊天室(基于Nodejs) socket.io简介 在Html5中存在着这样的一个新特性,引入了websocket,关于websocket的内部实现原理可以看这篇文章,这 ...

  2. java基础篇18-网络编程的常识和基于TCP协议的编程模型

    1.网络编程的常识   目前主流的网络通讯软件有:微信.QQ.YY.陌陌.探探.飞信.阿里旺旺....   在吗?  1.1 七层网络模型   为了保证数据传递的可靠安全等等,ISO(国际标准委员会组 ...

  3. java课程设计qq,模块java课程设计报告qq聊天

    河南工业大学 课程设 计 课程设计名称: ja  a qq聊天系统 学生姓名 : x  aoy    指导教 师: 王高平 课程设计时间: 2016.7.7 计科 专业课程设计任务书 说明: ...

  4. Socket编程(三)---仿QQ多人聊天实例

    从上篇文章我们实现了一个简单的socket实例.实例的功能为当一个客户端连接服务端的时候,服务端打印客户端的连接信息,并向客户端发送一组数据并在服务端接收数据和打印,数据内容为服务器当前时间. 这次的 ...

  5. Python多人聊天室-基于socket UDP协议

    简介 使用Python编写的基于socket UDP通信的多功能即时聊天室,包含Tkinter编写的图形化聊天界面,功能包括有账号注册和登录,登录成功后可以查看在线用户,并和聊天室内的其他在线用户聊天 ...

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

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

  7. php 多人聊天室,基于swoole实现多人聊天室,聊天室实现

    namespace app\common;require_once 'Predis.php';require_once 'Task.php';/** * socket面向对象的编译*/ classWs ...

  8. 基于Python的多人聊天室的设计与实现

    基于Python的多人聊天室的设计与实现 摘要  本文介绍了基于即时通讯的Python实现web版多人聊天室的设计和实现.这个系统利用了多种先进的技术,如Django.Channels.WebSock ...

  9. Java 多人聊天室

    Java实训做的多人聊天室,效果如图: 功能: 能够实现多个客户端之间的互相聊天,服务端来负责接收数据和转发数据. 每个客户端可以自己设置和修改自己的名称,并传给服务器让其他客户端知道. 当有客户端加 ...

最新文章

  1. 【博客话题】我的Linux虽然年轻,但是已经喜欢上她了...
  2. 特征选择与特征权重区别
  3. 青海高考成绩查询日期2021,2021年青海高考成绩什么时候出来 公布时间
  4. mint java_Linux mint使用
  5. 实用脚本!Python 提取 PDF 指定内容生成新文件!
  6. 多思计组原理虚拟实验室_先睹为快!汽院实验室组团来亮相_搜狐汽车
  7. TensorFlow 官方文档中文版
  8. 2018/7/18-纪中某C组题【jzoj3508,jzoj3509,jzoj3510,jzoj3512】
  9. laravel 提交Request 请求后会莫名多出一个s参数,导致数据库报错问题的解决方法
  10. IOS 如何获取ppi
  11. HDU2516 取石子游戏(斐波那契)
  12. 批处理bat命令快速截图
  13. sierpinski三角形的维数_分形维数算法
  14. A Knee_Guided Evolutionary Algorithm for Compressing Deep Neural Network (KGEA)解读
  15. android m是什么版本号,Android M版本号确定,并不是Android 6.0
  16. React 运行流程
  17. 学习MonoRail MVC
  18. 计算机打开共享网络连接打印机共享打印机,网络共享打印机连接不上怎么办_电脑连不上共享打印机如何解决-win7之家...
  19. Dell(戴尔)笔记本加装内存条后出现警告:“Warning Message : Alter!The amount of system memory has changed”
  20. Java函数式编程学习——Stream流

热门文章

  1. 由拖库攻击谈口令字段的加密策略
  2. 【z变换】1. z变换
  3. 计算机vf结束语句,计算机二级VF SQL语句常考总结。
  4. SMTP 客户端 msmtp mutt
  5. keras实现resnet50
  6. Fedora31开机启动自己的图形界面
  7. 交社保当中有一年领取失业金,会影响退休吗?
  8. 阿里云ACE高级认证考试试卷内容范围(云计算架构师)
  9. 操作系统—概述思维导图梳理结构及知识点
  10. 交换机或者路由器下面继续串小路由器掉线