Java之简单的聊天工具
今天整理资料的时候,找出自己几年前刚学Java时做过的一个简易的聊天工具,有服务器也有客户端,能发送文字消息和文件,但是用户上线并未存入数据库,而只是简单的缓存在服务器的一个数组中,所以,只要服务器一关闭,所有用户数据都会消失,界面是用第三方包,很简单,有点丑陋,不喜勿喷。
源码地址:http://download.csdn.net/detail/weidi1989/5810475
(GB2312编码方式,基于JDK1.7编译,如果直接导入eclipse出问题,请自行百度解决,3Q)
在运行代码之前,我们需要先作一下配置:
①服务器配置:如下图所示,找到Constants.java文件打开,将SERVER_IP改成你电脑对应的ip地址即可,端口视情况改变。
②客户端配置:同样如下图所示,找到Constants.java类,将SERVER_IP以及SERVER_PORT改成与服务器对应(这个很重要)
③先运行服务器,再运行客户端。
下面,我们来看看具体效果图:
1.先运行服务器,然后运行客户端,即可显示如下界面,同一局域网内的用户,会自动添加到好友列表中。
2.测试文字聊天,只是简单发送文字消息,丑陋程度就不提了
3.测试文件发送与接收,发送的文件内容请忽视哦!
简单的思路分析:
①服务器监听一个端口,时时等待用户的连接,当有用户上线时,经过几次握手成功,将该用户存入一个在线用户缓存器:UserCache。
②文字消息都是通过服务器转发的,用户首先将文字消息封装成一个对象(这个对象包含文字消息内容、来自哪里ip、发送给谁ip等),发送到服务器,服务器再从在线用户缓存器中遍历出要发送的对象ip,然后转发给该用户,即完成转发,跟我的Android之高仿手机QQ聊天是类似的。
③文件传输,是用户之间单独建立连接的,当一方要给另一方发送文件时,先通过服务器转发该文件大小、名称等信息,告知对方是否接收文件,如果对方接收,即启动一个监听文件传书的Socket,然后再回馈该信息(也是通过服务器转发)给另一方,此时启动一个线程Socket去连接对方发送文件(这中间,最好是加上超时判断,我这里很简单,就没有处理)。另外需要注意的是,我这里是通过SwingWorker来更新界面的,有点类似于Android的AsyncTask,做过Android的童鞋应该就很清楚了。
由于是代码年代比较久远,也难免会有些细节会忘记,所以详细代码我就不给大家分析了,其实是很简单的,想学习一下的童鞋可以下载源码参考一下,下面我们来看看重要的两个部分代码:
Server.java:
- /**
- * 服务器,接受用户登录、离线
- *
- * @author way
- *
- */
- public class Server {
- private ServerSocket serverSocket = null;
- private UserCache userCache = UserCache.getInstance();// 用户缓存器
- private Transffer transffer = new TransfferImpl();
- private boolean isStarted = true;
- public Server() {
- InetAddress address;
- try {
- address = InetAddress.getByName(Constants.SERVER_IP);
- serverSocket = new ServerSocket(Constants.SERVER_PORT, 0, address);
- } catch (UnknownHostException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- System.exit(0);
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- System.exit(0);
- }
- }
- public void start() {
- while (isStarted) {
- try {
- Socket socket = serverSocket.accept();
- TranObject object = transffer.get(socket);
- process(socket, object);
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (ClassNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
- /**
- * 对来自用户的请求进行处理
- *
- * @param socket
- * @param object
- */
- private void process(Socket socket, TranObject object) {
- LLogger.info("接收到用户消息!");
- switch (object.getType()) {
- case LOGIN:
- login(socket, object);
- break;
- case LOGOUT:
- logout(socket, object);
- break;
- }
- }
- /**
- * 登录,登录完成后要向所有在线用户通报
- * @param socket
- * @param object
- */
- private void login(Socket socket, TranObject object) {
- LLogger.info("用户登录:" + object.getFromUser().getIp());
- userCache.add(object.getFromUser());
- TranObject<Set<User>> o = new TranObject<Set<User>>(
- TranObjectType.LOGIN);
- o.setToUser(object.getFromUser());
- o.setObject(userCache.get());
- try {
- transffer.tran(socket, o);
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- //需要向所有用户发送该用户登录消息
- TranObject<User> loginO = new TranObject<User>(TranObjectType.LOGIN);
- loginO.setObject(object.getFromUser());
- broadcast(loginO);
- }
- /**
- * 离线,离线完成后要向所有在线用户通报
- * @param socket
- * @param object
- */
- private void logout(Socket socket, TranObject object) {
- LLogger.info("用户离线:" + object.getFromUser().getIp());
- userCache.delete(object.getFromUser());
- //需要向所有用户发送用户离线消息
- TranObject<User> logoutO = new TranObject<User>(TranObjectType.LOGOUT);
- logoutO.setObject(object.getFromUser());
- broadcast(logoutO);
- }
- /**
- * 向所有在线用户发送广播包
- *
- * @param object
- */
- private void broadcast(TranObject object){
- Set<User> set = userCache.get();
- for(User u: set){
- object.setToUser(u);
- try {
- transffer.tranNoResponse(object);
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (ClassNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
- public static void main(String[] args) {
- new Server().start();
- }
- }
下面是Client.java:
- /**
- * 客户端
- * 需要启动:
- * 1. 客户端消息服务器监听
- * 2. 消息处理器
- * 3. 登录并显示界面
- *
- * @author way
- *
- */
- public class Client {
- private User user = new User();
- private ClientSender sender = ClientSenderImpl.getInstance();
- private MessageProcessor messageProcessor = new MessageProcessor();//消息处理器
- private ClientServer server;//消息监听器
- private MainFrame frame = new MainFrame(this);
- private Cache cache = Cache.getInstance();
- public Client(String name){
- user.setName(name);
- user.setPort(Constants.CLIENT_SERVER_PORT);
- String ip = "";
- try {
- ip = getIp();
- } catch (UnknownHostException e1) {
- e1.printStackTrace();
- }
- if(ip==null
- ||ip.equals("")){
- JOptionPane.showMessageDialog(null,"获取本机IP失败! ");
- return;
- }
- user.setIp(ip);
- cache.setNowUser(user);
- if(!login()){
- JOptionPane.showMessageDialog(null,"无法与服务器建立连接!");
- return;
- }
- /**
- * 启动消息处理器
- */
- messageProcessor.execute();
- /**
- * 启动服务器
- */
- try {
- server = new ClientServer(frame,ip);
- server.execute();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- JOptionPane.showMessageDialog(null, "端口已被占用,程序退出!");
- System.exit(0);
- }
- //显示主窗口
- // AWTUtilities.setWindowOpacity(frame, 1f);
- frame.addWindowListener(new WindowListener(){
- @Override
- public void windowOpened(WindowEvent e) {
- // TODO Auto-generated method stub
- }
- @Override
- public void windowClosing(WindowEvent e) {
- }
- @Override
- public void windowClosed(WindowEvent e) {
- // TODO Auto-generated method stub
- System.exit(0);
- }
- @Override
- public void windowIconified(WindowEvent e) {
- // TODO Auto-generated method stub
- }
- @Override
- public void windowDeiconified(WindowEvent e) {
- // TODO Auto-generated method stub
- }
- @Override
- public void windowActivated(WindowEvent e) {
- // TODO Auto-generated method stub
- }
- @Override
- public void windowDeactivated(WindowEvent e) {
- // TODO Auto-generated method stub
- }
- });
- frame.setVisible(true);
- }
- private String getIp() throws UnknownHostException{
- String ip = InetAddress.getLocalHost().getHostAddress();
- return ip;
- }
- /**
- * 退出操作
- * @return
- */
- public void logout(){
- LLogger.info("用户退出登录!");
- sender.logout();
- }
- /**
- * 登录
- */
- private boolean login(){
- try {
- Set<User> userSet = null;
- userSet = sender.login();
- frame.getCenterPanel().addUser(userSet);
- return true;
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (ClassNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return false;
- }
- public static void main(String[] args){
- UIManager.put("swing.boldMetal", Boolean.FALSE);
- new Client("测试");
- }
- }
Java之简单的聊天工具的更多相关文章
- python 开发简单的聊天工具
python 太强大了,以至于它什么都可以做,哈哈,开个玩笑.但是今天要讲的真的是一个非常神奇的应用. 使用python写一个聊天工具 其实大家平时用的QQ类似的聊天工具,也是使用socket进行聊天 ...
- python 开发简单的聊天工具-乾颐堂
python 太强大了,以至于它什么都可以做,哈哈,开个玩笑.但是今天要讲的真的是一个非常神奇的应用. 使用python写一个聊天工具 其实大家平时用的QQ类似的聊天工具,也是使用socket进行聊天 ...
- JAVA WebSocKet ( 简单的聊天室 )
1, 前端代码 登入页 -> login.html <!DOCTYPE html> <html> <head> <meta charset=" ...
- Java一个简单的文件工具集
class FileUtils { //文件目录下文件总数目 public static int fileNumber(File dir) { int filenumber = 0; if(dir.e ...
- [更新Github地址]python学习,自己写了个简单聊天工具mychat
最近在学习python,自己写了个最最简单的聊天工具mychatv0.1. 第一版,完成基本的聊天功能. GUI用的是自带的TKinter,用到的模块主要就是socket(网络编程), thread( ...
- RDIFramework.NET ━ .NET快速信息化系统开发框架 V2.8 版本━新增企业通(内部简易聊天工具)
RDIFramework.NET ━ .NET快速信息化系统开发框架 V2.8 版本 新增企业通(内部简易聊天工具) RDIFramework.NET,基于.NET的快速信息化系统开发.整合框架,给用 ...
- 聊天工具mychat
python学习,自己写了个简单聊天工具mychat 最近在学习python,自己写了个最最简单的聊天工具mychatv0.1. 第一版,完成基本的聊天功能. GUI用的是自带的TKinter,用到的 ...
- java Socket实现简单在线聊天(三)
在上一篇,利用线程使服务端实现了能够接收多客户端请求的功能,这里便需要客户端接收多客户端消息的同时还能把消息转发到每个连接的客户端,并且客户端要能在内容显示区域显示出来,从而实现简单的在线群聊. 在实 ...
- java Socket实现简单在线聊天(二)
接<java Socket实现简单在线聊天(一)>,在单客户端连接的基础上,这里第二步需要实现多客户端的连接,也就需要使用到线程.每当有一个新的客户端连接上来,服务端便需要新启动一个线程进 ...
随机推荐
- 7月12日至芯FPGA就业班招生
至芯科技FPGA就业培训班将于2014年7月12日正式开班,届时至芯科技将秉承着一贯的教学传统,为广大师生打造一个专业的技术平台和轻松的学习环境. 在夏宇闻教授的带领下,至芯科技汇聚了一批来自国内外大 ...
- History Grading
uva111:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=24& ...
- SDUT2484 算术表达式的转换(表达式树)
题目链接. 分析: 转换成表达式树,然后先序.中序.后序遍历. AC代码如下: #include <stdio.h> #include <string.h> #define m ...
- 【转】Unable to execute dex: Java heap space 解决方案(如何为eclipse.int 添加内存)
原文网址:http://blog.csdn.net/zengyangtech/article/details/7003379 欢迎转载,转载请注明 http://blog.csdn.net/zengy ...
- sql存储过程的创建
一:没有参数的存储过程 CREATE PROCEDURE select_all AS BEGIN SELECT * from T_login1 END GO 二:带参数的存储过程 CREATE PRO ...
- Windows 10 代理上网用户的正确使用姿势
1.找不到IE,如何使用IE来配置局域网代理 打开Edge浏览器,点击选项,找到“使用Internet Explorer打开” 接下来可以使用熟练的姿势设置IE局域网代理上网了 2.Windows ...
- 乱译文档--开始使用Musca
原文地址:http://aerosuidae.net/musca_start.html aerosuidae.net Musca - Start Using startx Launch it from ...
- Linux文件操作学习总结【转载】
本文转载自: http://blog.csdn.net/xiaoweibeibei/article/details/6556951 文件类型:普通文件(文本文件,二进制文件).目录文件.链接文件.设备 ...
- bda_百度百科
bda_百度百科 bda
- A - 敌兵布阵 - hdu 1166
Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些 ...