【Java课程设计】仿QQ多人聊天室(基于TCP协议与JavaSwing)附下载
仿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)附下载相关推荐
- node php聊天室,利用socket.io实现多人聊天室(基于Nodejs)
利用socket.io实现多人聊天室(基于Nodejs) socket.io简介 在Html5中存在着这样的一个新特性,引入了websocket,关于websocket的内部实现原理可以看这篇文章,这 ...
- java基础篇18-网络编程的常识和基于TCP协议的编程模型
1.网络编程的常识 目前主流的网络通讯软件有:微信.QQ.YY.陌陌.探探.飞信.阿里旺旺.... 在吗? 1.1 七层网络模型 为了保证数据传递的可靠安全等等,ISO(国际标准委员会组 ...
- java课程设计qq,模块java课程设计报告qq聊天
河南工业大学 课程设 计 课程设计名称: ja a qq聊天系统 学生姓名 : x aoy 指导教 师: 王高平 课程设计时间: 2016.7.7 计科 专业课程设计任务书 说明: ...
- Socket编程(三)---仿QQ多人聊天实例
从上篇文章我们实现了一个简单的socket实例.实例的功能为当一个客户端连接服务端的时候,服务端打印客户端的连接信息,并向客户端发送一组数据并在服务端接收数据和打印,数据内容为服务器当前时间. 这次的 ...
- Python多人聊天室-基于socket UDP协议
简介 使用Python编写的基于socket UDP通信的多功能即时聊天室,包含Tkinter编写的图形化聊天界面,功能包括有账号注册和登录,登录成功后可以查看在线用户,并和聊天室内的其他在线用户聊天 ...
- Python实现群聊天室(基于TCP)
一.服务端代码: 1. 需要socket,threading 这两个模块 2.使用单进程多线程实现: 1)多个客户端同时在线群聊 2)新客户端上线广播通知其他在线客户端 3)在线客户端下线广播通知其他 ...
- php 多人聊天室,基于swoole实现多人聊天室,聊天室实现
namespace app\common;require_once 'Predis.php';require_once 'Task.php';/** * socket面向对象的编译*/ classWs ...
- 基于Python的多人聊天室的设计与实现
基于Python的多人聊天室的设计与实现 摘要 本文介绍了基于即时通讯的Python实现web版多人聊天室的设计和实现.这个系统利用了多种先进的技术,如Django.Channels.WebSock ...
- Java 多人聊天室
Java实训做的多人聊天室,效果如图: 功能: 能够实现多个客户端之间的互相聊天,服务端来负责接收数据和转发数据. 每个客户端可以自己设置和修改自己的名称,并传给服务器让其他客户端知道. 当有客户端加 ...
最新文章
- 【博客话题】我的Linux虽然年轻,但是已经喜欢上她了...
- 特征选择与特征权重区别
- 青海高考成绩查询日期2021,2021年青海高考成绩什么时候出来 公布时间
- mint java_Linux mint使用
- 实用脚本!Python 提取 PDF 指定内容生成新文件!
- 多思计组原理虚拟实验室_先睹为快!汽院实验室组团来亮相_搜狐汽车
- TensorFlow 官方文档中文版
- 2018/7/18-纪中某C组题【jzoj3508,jzoj3509,jzoj3510,jzoj3512】
- laravel 提交Request 请求后会莫名多出一个s参数,导致数据库报错问题的解决方法
- IOS 如何获取ppi
- HDU2516 取石子游戏(斐波那契)
- 批处理bat命令快速截图
- sierpinski三角形的维数_分形维数算法
- A Knee_Guided Evolutionary Algorithm for Compressing Deep Neural Network (KGEA)解读
- android m是什么版本号,Android M版本号确定,并不是Android 6.0
- React 运行流程
- 学习MonoRail MVC
- 计算机打开共享网络连接打印机共享打印机,网络共享打印机连接不上怎么办_电脑连不上共享打印机如何解决-win7之家...
- Dell(戴尔)笔记本加装内存条后出现警告:“Warning Message : Alter!The amount of system memory has changed”
- Java函数式编程学习——Stream流