详解基于java的Socket聊天程序——初始设计(附demo)

作者:jAVA-yaolin 时间:2023-02-01 06:46:21 

写在前面:

可能是临近期末了,各种课程设计接踵而来,最近在csdn上看到2个一样问答,那就是编写一个基于socket的聊天程序,正好最近刚用socket做了一些事,出于兴趣,自己抽了几个晚上的空闲时间敲了一个,目前仅支持单聊,群聊,文件传送这些功能。首先,贴出一个丑丑的程序图(UI是用java swing写的,这个早就忘光了,无奈看着JDK的API写了一个),如下图:

详解基于java的Socket聊天程序——初始设计(附demo)

 服务端设计:

服务端主要有两个操作,一是阻塞接收客户端的socket并做响应处理,二是检测客户端的心跳,如果客户端一段时间内没有发送心跳则移除该客户端,由Server创建ServerSocket,然后启动两个线程池去处理这两件事(newFixedThreadPool,newScheduledThreadPool),对应的处理类分别是SocketDispatcher、SocketSchedule,其中SocketDispatcher根据socket不同的请求分发给不同SocketHandler去处理,而SocketWrapper则是对socket加了一层外壳包装,用lastAliveTime记录socket最新的交互时间,SocketHolder存储当前跟服务端交互的socket集合。设计如下:

详解基于java的Socket聊天程序——初始设计(附demo)

客户端设计:

客户端设计主要分成两个部分,分别是socket通讯模块设计和UI相关设计

客户端socket通讯设计,这里的设计其实跟服务端的设计差不多,不同的是服务端是接收心跳包,而客户端是发送心跳包,由于客户端只与一个服务端进行通讯(客户端之间的通讯也是由服务端进行分发的),所以这里只使用了一个大小为2的线程池去处理这两件事(newFixedThreadPool(2)),对应的处理类分别是ReceiveListener、KeepAliveDog,其中ReceiveListener在初始化的时候传入一个Callback作为客户端收到服务端的消息的回调,Callback的默认实现是DefaultCallback,DefaultCallback根据不同的事件通过HF分发给不同Handler去处理,而ClientHolder则是存储当前客户端信息,设计如下:

详解基于java的Socket聊天程序——初始设计(附demo)

UI相关设计,这里我不打算自己写UI,毕竟自己写出来的太丑了,所以后期可能会叫同学或朋友帮忙敲一下,所以我将UI的事件处理都交由Action去处理,将UI设计和事件响应简单分离,所有UI继承JFrame并实现View接口,上面的Handler实现类通过Router获取(存在则直接返回,不存在则创建并存储)指定的UI,View中提供了UI的创建create()、获取container()、获取UI中的组件getComponent(),显示display(),回收trash();ResultWrapper和ResultHolder只是为了创建和存储聊天选项卡。

详解基于java的Socket聊天程序——初始设计(附demo)

 Common模块设计:

Common模块主要是数据交互,这里使用JSON数据进行交互,common模块定义了各类交互信息,SendHelper实现的socket信息的传送,I18N是语言话,ConstantValue是系统中的配置以及常量(这里常量都是用接口,这个可能不太好),对于ReturnMessage拥有一系列的DTO作为其content属性。

详解基于java的Socket聊天程序——初始设计(附demo)

 程序入口:

最后给出服务端和客户端的入口程序(完整代码挂在csdn上,有时间会持续更新,文章最后有地址)

服务端入口:


package yaolin.chat.server;

import java.io.IOException;
import java.net.ServerSocket;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import yaolin.chat.common.ConstantValue;
import yaolin.chat.util.LoggerUtil;

/**
* 服务器
* @author yaolin
*/
public class Server {

private final ServerSocket server;
 private final ExecutorService pool;

public Server() throws IOException {
   server = new ServerSocket(ConstantValue.SERVER_PORT);
   pool = Executors.newFixedThreadPool(ConstantValue.MAX_POOL_SIZE);
 }

public void start() {
   try {
     ScheduledExecutorService schedule = Executors.newScheduledThreadPool(1);
     // Watch dog. Exception??
     schedule.scheduleAtFixedRate(new SocketSchedule(), 10, ConstantValue.TIME_OUT, TimeUnit.SECONDS);

while (true) {
       pool.execute(new SocketDispatcher(server.accept()));
       LoggerUtil.info("ACCEPT A CLIENT AT " + new Date());
     }
   } catch (IOException e) {
     pool.shutdown();
   }
 }

public static void main(String[] args) {
   try {
     new Server().start();
   } catch (IOException e) {
     LoggerUtil.error("Server start failed! -> " + e.getMessage(), e);
   }
 }
}

客户端入口:


package yaolin.chat.client;

import java.io.IOException;

import javax.swing.JOptionPane;

import yaolin.chat.client.callback.DefaultCallback;
import yaolin.chat.client.view.Router;
import yaolin.chat.client.view.impl.RegisterAndLoginView;

/**
*
* @author yaolin
*
*/
public class NiloayChat {

public static void main(String[] args) {
   RegisterAndLoginView v = (RegisterAndLoginView) Router.getView(RegisterAndLoginView.class).create();
   try {
     v.display();
     Client client = new Client(new DefaultCallback());
     client.start();
     ClientHolder.setClient(client);
   } catch (IOException e) {
     JOptionPane.showMessageDialog(v.getContentPane(), e.getMessage());
   }
 }
}

源码下载:demo

来源:http://www.cnblogs.com/niloay/p/socket-chat.html

标签:java,socket,聊天室
0
投稿

猜你喜欢

  • 简单聊一聊Java线程池ThreadPoolExecutor

    2021-10-23 15:56:58
  • mybatis 插件: 打印 sql 及其执行时间实现方法

    2023-05-29 16:49:19
  • C# ODP.NET 调用Oracle函数返回值时报错的一个解决方案

    2021-10-03 01:54:19
  • Springboot整合支付宝支付功能

    2023-07-02 17:38:09
  • Groovy编程入门攻略

    2022-12-05 13:35:47
  • maven依赖版本没有按照最短路径原则生效的解决方案

    2023-04-04 20:49:09
  • JAVA反射机制实例详解

    2021-11-08 13:39:34
  • WPF ProgressBar实现实时进度效果

    2023-01-14 08:05:49
  • Spring Data JPA 设置字段默认值方式

    2021-08-13 07:27:06
  • VisualStudio Community2019在安装的过程中无法进入安装界面的解决方法

    2023-02-09 11:24:34
  • Java实现经典游戏复杂迷宫

    2021-05-29 22:33:34
  • Android崩溃异常捕获方法

    2022-08-24 08:26:12
  • JavaWeb实现文件上传下载功能实例解析

    2023-10-07 17:41:39
  • 使用java从乱码文本中解析出正确的文本

    2023-12-03 12:10:22
  • Java HtmlEmail 邮件发送的简单实现代码

    2023-04-14 21:29:25
  • java io文件操作从文件读取数据的六种方法

    2023-05-17 02:54:40
  • Android圆形头像拍照后“无法加载此图片”的问题解决方法(适配Android7.0)

    2023-11-18 23:26:56
  • java实现简单的扫雷小游戏

    2022-09-14 19:23:24
  • Android仿简书搜索框效果的示例代码

    2023-06-18 16:02:58
  • Spring与Spring boot的区别介绍

    2022-02-12 08:55:07
  • asp之家 软件编程 m.aspxhome.com