欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2024-03-09 11:51:41
写在前面: 可能是临近期末了,各种课程设计接踵而来,最近在csdn上看到2个一样问答,那就是编写一个基于socket的聊天程序,正好最近刚用socket做了一些事,出于兴...

写在前面:

可能是临近期末了,各种课程设计接踵而来,最近在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());
    }
  }
}


源码下载:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。