1. 当前位置:网站首页 > 编程语言

基于C/S的网盘设计(使用JAVA实现)


基于C/S的网盘设计(JAVA)

由于有其他的工作,网盘做了一部分不得不放手了,

我希望有时间的其他朋友可以继续工作,虽然网络上有很多现成的网盘代码,不过还是希望自己能做一个,并借鉴一些优秀的思想来实现,下面说下实现过程,有些部分需要改进

一、数据库的设计,目前只涉及到用户表,当然还有其他的,你可以根据需要来增加

#用户表
create table m_user(
 id int primary key auto_increment,
 name varchar(32) not null unique,
 password char(32) not null,
 `gender` enum('
','') NOT NULL DEFAULT '',
 phone varchar(20),
 email varchar(50) not null,
 reg_date char(16) not null,
 reg_ip varchar(15) not null,
 last_login_date char(16),
 last_login_ip varchar(15)
);

二、数据源的设置,我这里使用c3p0数据源,当然你可以使用dbcp或者其他的

配置c3p0-config.xml文件就可以了,网络上有详细的配置项,或者在我源码里面下载,在最后公布下载地址

在这里我写一个简单的JdbcUtil,当然还可以编写一些复杂的操作,工作不允许我继续往下写了,你可以集成一些操作,就像hibernate那样

public class JdbcUtil {

    /**     * 数据库连接管理器

     */

//    private static Logger log = Logger.getLogger(JdbcUtil.class);

    /*初始化数据库连接池*/

    private static DataSource dataSource = new ComboPooledDataSource();

   

    /*获取数据源*/

    public DataSource getDataSource(){

        return dataSource;

    }

   

    /*获取连接*/

    public static Connection getConnection() throws SQLException{

        return dataSource.getConnection();

    }

   

    /*释放连接*/

    public static void free(ResultSet rs,PreparedStatement ps,Connection conn){

        if(null != rs){

            try {

                rs.close();

            } catch (SQLException e) {}

        }

        if(null != ps){

            try {

                ps.close();

            } catch (SQLException e) {}

        }

        if(null != conn){

            try {

                conn.close();

            } catch (SQLException e) {}

        }

    }

    public static void free(PreparedStatement ps,Connection conn){

        if(null != ps){

            try {

                ps.close();

            } catch (SQLException e) {}

        }

        if(null != conn){

            try {

                conn.close();

            } catch (SQLException e) {}

        }

    }

}


三、我这里先说说服务端

1.socket线程池

池的作用想必大家都知道,循环利用资源,我这里的这个池只是简单的池,没有时间再完成一个复杂的工作了

cn.mike.server.ServerThread是一个负责处理用户请求的线程,我们要创建一批这样的线程,并由cn.mike.server.ServerThreadPool管理,代码如下:

public class ServerThreadPool {

    /**     * 服务端线程池

     */

    private final static Logger log = Logger.getLogger(ServerThreadPool.class);

    //线程组

    public static LinkedList<ServerThread> threadPool = new LinkedList<ServerThread>();

    private static int maxPoolSize;//最大连接数

    private static int minPoolSize;//最小连接数

    private static int initialPoolSize;//初始化连接数

    private static int maxIdleTime;//连接的最大空闲时间,单位:

    private static int acquireIncrement;//在当前连接数耗尽的时候,一次获取的新的连接数

    static int maxWaitUserTime;//线程等待用户操作的最大时间,到达最大时间未传送数据,则进行线程释放

   

    public ServerThreadPool(){

        initProperties();

        initThreadPool();

    }

   

    /*     * 初始化配置

     */

    public void initProperties(){

        System.out.println("正在启动线程池...");

        System.out.println("正在加载线程池配置文件...");

        Properties pro = new Properties();

        HashMap<String, String> propertiesMap = new HashMap<String, String>();

        try {

            pro.load(ServerThreadPool.class.getClassLoader().getResourceAsStream(ServerThreadPoolConfig.PROPS_FILE_RSRC_PATH));

            propertiesMap.put(ServerThreadPoolConfig.MAX_POOL_SIZE, pro.getProperty(ServerThreadPoolConfig.MAX_POOL_SIZE));

            propertiesMap.put(ServerThreadPoolConfig.MIN_POOL_SIZE, pro.getProperty(ServerThreadPoolConfig.MIN_POOL_SIZE));

            propertiesMap.put(ServerThreadPoolConfig.INITIAL_POOL_SIZE, pro.getProperty(ServerThreadPoolConfig.INITIAL_POOL_SIZE));

            propertiesMap.put(ServerThreadPoolConfig.MAX_IDLE_TIME, pro.getProperty(ServerThreadPoolConfig.MAX_IDLE_TIME));

            propertiesMap.put(ServerThreadPoolConfig.ACQUIRE_INCREMENT, pro.getProperty(ServerThreadPoolConfig.ACQUIRE_INCREMENT));

            propertiesMap.put(ServerThreadPoolConfig.MAX_WAIT_USER_TIME, pro.getProperty(ServerThreadPoolConfig.MAX_WAIT_USER_TIME));

            if(null != propertiesMap.get(ServerThreadPoolConfig.MAX_POOL_SIZE)){

                ServerThreadPool.maxPoolSize = Integer.parseInt(propertiesMap.get(ServerThreadPoolConfig.MAX_POOL_SIZE));

            }else{

                ServerThreadPool.maxPoolSize = 100;

            }

           

            if(null != propertiesMap.get(ServerThreadPoolConfig.MIN_POOL_SIZE)){

                ServerThreadPool.minPoolSize = Integer.parseInt(propertiesMap.get(ServerThreadPoolConfig.MIN_POOL_SIZE));

            }else{

                ServerThreadPool.minPoolSize = 5;

            }

           

            if(null != propertiesMap.get(ServerThreadPoolConfig.INITIAL_POOL_SIZE)){

                ServerThreadPool.initialPoolSize = Integer.parseInt(propertiesMap.get(ServerThreadPoolConfig.INITIAL_POOL_SIZE));

            }else{

                ServerThreadPool.initialPoolSize = 5;

            }

           

            if(null != propertiesMap.get(ServerThreadPoolConfig.MAX_IDLE_TIME)){

                ServerThreadPool.maxIdleTime = Integer.parseInt(propertiesMap.get(ServerThreadPoolConfig.MAX_IDLE_TIME));

            }else{

                ServerThreadPool.maxIdleTime = 10;

            }

           

            if(null != propertiesMap.get(ServerThreadPoolConfig.ACQUIRE_INCREMENT)){

                ServerThreadPool.acquireIncrement = Integer.parseInt(propertiesMap.get(ServerThreadPoolConfig.ACQUIRE_INCREMENT));

            }else{

                ServerThreadPool.acquireIncrement = 1;

            }

            if(null != propertiesMap.get(ServerThreadPoolConfig.MAX_WAIT_USER_TIME)){

                ServerThreadPool.maxWaitUserTime = Integer.parseInt(propertiesMap.get(ServerThreadPoolConfig.MAX_WAIT_USER_TIME));

            }else{

                ServerThreadPool.maxWaitUserTime = 60000;

            }

           

        } catch (Exception e) {

            log.error("线程池配置文件加载出错,请确保文件threadPool.properties存在,并正确配置!");

            System.exit(1);

        }

        System.out.println("线程池配置加载成功,配置信息如下:");

        System.out.println("#################################");

        System.out.println("最大连接数:"+ServerThreadPool.maxPoolSize);

        System.out.println("最小连接数:"+ServerThreadPool.minPoolSize);

        System.out.println("初始化连接数:"+ServerThreadPool.initialPoolSize);

        System.out.println("连接的最大空闲时间:"+ServerThreadPool.maxIdleTime+" ");

        System.out.println("在当前连接数耗尽的时候,一次获取的新的连接数:"+ServerThreadPool.acquireIncrement);

        System.out.println("线程等待用户操作的最大时间:"+ServerThreadPool.maxWaitUserTime+" 毫秒");

        System.out.println("#################################");

    }

    /*     * 初始化服务线程

     */

    public void initThreadPool(){

        for(int i=0;i<ServerThreadPool.initialPoolSize;i++){

            ServerThread st = new ServerThread();

            st.start();

            threadPool.add(st);

        }

    }

   

    /*     * 线程池动态调整器

     */

    public void poolAdjust(){

       

    }

}


一些配置规范我把它放在cn.mike.server.ServerThreadPoolConfig

public class ServerThreadPoolConfig {

    /*     * 线程池配置

     */

   

    //配置文件路径

    public final static String PROPS_FILE_RSRC_PATH     = "threadPool.properties";

    //最大连接数

    public final static String MAX_POOL_SIZE = "maxPoolSize";

    //最小连接数

    public final static String MIN_POOL_SIZE = "minPoolSize";

    //初始化连接数

    public final static String INITIAL_POOL_SIZE= "initialPoolSize";

    //连接的最大空闲时间,单位:

    public final static String MAX_IDLE_TIME = "maxIdleTime";

    //在当前连接数耗尽的时候,一次获取的新的连接数

    public final static String ACQUIRE_INCREMENT = "acquireIncrement";

    //线程等待用户操作的最大时间,到达最大时间未传送数据,则进行线程释放

    public final static String MAX_WAIT_USER_TIME = "maxWaitUserTime";

   

}

threadPool.properties文件用于配置线程池的一些选项,我这里的设置可能不够完整,你可以根据需要增加

还有一个重要问题,这里需要开启一个线程来管理线程池里线程的数量,实现动态调整,这工作我并没完成,希望你能把它完成

cn.mike.server.Server是一个用于接收用户请求的分配器,处理一些初始化工作

public class Server {

    /**     * 25 网盘 服务端

     */

    private final static Logger log = Logger.getLogger(Server.class);

    private int listenPort = 8594;//监听端口

    private static ServerSocket ss;

    static LinkedList<Socket> taskQueue = new LinkedList<Socket>();//任务队列

    public static Map<String,Session> sessionMap = new HashMap<String,Session>();

    /*初始化线程池*/    ServerThreadPool stp = new ServerThreadPool();

    /*数据库连接工具*/

    public JdbcUtil jdbcUtil = new JdbcUtil();

    private int maxWaitUserTime = ServerThreadPool.maxWaitUserTime;//最大等待操作时间

   

    public static void main(String[] args) {

        System.out.println("正在启动服务器...");

        Server server = new Server();

        new TaskHandle().start();

        server.init();

    }

    public void init(){

//        初始化数据库连接池

        System.out.println("正在初始化数据库连接池...");

        try {

            System.out.println("#################################");

            JdbcUtil.getConnection().close();

            System.out.println("#################################");

            System.out.println("数据库连接池创建成功!");

        } catch (SQLException e1) {

            log.error("数据库连接池创建失败!");

            System.exit(1);

        }

       

        /*开启监听服务*/

        try {

            ss = new ServerSocket(listenPort);

            System.out.println("服务器启动成功,正在监听端口:"+listenPort);

            while(true){

                Socket socket = ss.accept();

                socket.setSoTimeout(maxWaitUserTime);//设置最大连接时长

                System.out.println("发现客户端连接,IP:"+socket.getRemoteSocketAddress());

                process(socket);//转入线程池处理

            }

        } catch (IOException e) {

            System.out.println("服务器启动失败,请确保端口:"+listenPort+"不被其他程序占用!");

        }

    }

   

    /*     * 服务线程处理客户端请求

     */

    public void process(Socket socket){

        if(ServerThreadPool.threadPool.size()>0){//如果池中还有服务线程

            ServerThreadPool.threadPool.removeFirst().startWork(socket);

        }

        else if(taskQueue.size()<1000){//若没有,并且队列长度小于1000,则加入任务队列

            taskQueue.add(socket);

        }

        else{

            try {

                socket.close();

            } catch (IOException e) {

                log.error("关闭客户端socket失败!");

            }

        }

    }

   

}

 

/* *开启定时器,处理任务队列,每隔 500 毫秒查看有没有空闲连接

 */

class TaskHandle extends Thread{

    static LinkedList<Socket> taskQueue =  Server.taskQueue;

    public TaskHandle(){

        System.out.println("队列任务处理器开启..");

    }

    public void run() {

        try {

            while(true){

                Thread.sleep(500);

                if(taskQueue.size()>0 && ServerThreadPool.threadPool.size()>0){//如果池中还有服务线程,则处理任务队列

                    ServerThreadPool.threadPool.removeFirst().startWork(Server.taskQueue.removeFirst());

                }

            }

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

    }

   

}

可能有些东西读者不是很明白,这需要对socket编程熟悉点,当然我的设计也有些问题,希望读者能提改进意见,有时间就修改

 


本文最后更新于2012-3-25,已超过 3个月没有更新,如果文章内容或图片资源失效,请留言反馈,我们会及时处理,谢谢!
版权说明

本文地址:https://blog.gengchao.cn/post-130.html
未标注转载均为本站远程,转载请注明文章出处:

发表评论

联系我们

在线咨询:点击这里给我发消息

微信号:cngengchao

工作日:9:00-23:00,节假日休息

扫码关注