`

Apache MiNa 实现多人聊天室

    博客分类:
  • Java
阅读更多

Apache MiNa 实现多人聊天室

开发环境:

System:Windows

JavaSDK:1.6

IDE:eclipse、MyEclipse 6.6

开发依赖库:

Jdk1.4+、mina-core-2.0.4.jar、slf4j-api-1.5.11.jar、slf4j-log4j12-1.5.11.jar

Email:hoojo_@126.com

Blog:http://blog.csdn.net/IBM_hoojo

http://hoojo.cnblogs.com/

http://hoojo.blogjava.net

前不久用Socket写的聊天程序,主要是手机端程序通过Socket连接服务器端的ServerSocket,然后服务器端根据客户端发送过来统一规范的报文。进行解析再用smack框架转发到openfire服务器,最后由openfire服务器向客户端程序发送聊天信息。

最近发现socket服务器资源消耗比较大。我是采用阻塞式多线程通信方式,这种方式会造成大量的服务器资源浪费、长期的占用服务器的CUP调度权,并且会长时间阻塞程序,等待客户端连接、发送消息等。

为了解决上面的状况,Apache MiNa能很好的解决这个问题。Mina采用的是非阻塞式、单线程、NIO通信方式。

非阻塞式通信的思想是:让一个线程同时完成多件事,这个线程会利用完成这件事的空余时间去完成另一件事,一刻也不闲着。这个线程同时也会不断监控每件事情中需要处理时间的发生,发生一个就处理一件,然后继续监听各自事情。

一、介绍

首先,Mina是个什么东西?看下官方网站(http://mina.apache.org/)对它的解释:

Apache的Mina(Multipurpose Infrastructure Networked Applications)是一个网络应用框架,可以帮助用户开发高性能和高扩展性的网络应用程序;它提供了一个抽象的、事件驱动的异步API,使Java NIO在各种传输协议(如TCP/IP,UDP/IP协议等)下快速高效开发。

Apache Mina也称为:

 NIO框架

 网络套接字(networking socket)类库

 事件驱动的异步API(注意:在JDK7中也新增了异步API)

总之:我们简单理解它是一个封装底层IO操作,提供高级操作API的通讯框架!

二、服务器端编码工作

第一步:

使用Apache MiNa框架,你需要下载jar

下载地址:http://mina.apache.org/dyn/closer.cgi/mina/2.0.4/apache-mina-2.0.4-bin.zip

你需要添加jar如下

clip_image002

如果你使用日志,需要添加日志配置文件log4j.properties

第二步:

编写通信要用的解码工厂和编码器、解码器类,代码如下

package com.hoo.mina.code.factory;
<!--CRLF-->
 
<!--CRLF-->
import org.apache.mina.core.session.IoSession;
<!--CRLF-->
import org.apache.mina.filter.codec.ProtocolCodecFactory;
<!--CRLF-->
import org.apache.mina.filter.codec.ProtocolDecoder;
<!--CRLF-->
import org.apache.mina.filter.codec.ProtocolEncoder;
<!--CRLF-->
import com.hoo.mina.code.CharsetDecoder;
<!--CRLF-->
import com.hoo.mina.code.CharsetEncoder;
<!--CRLF-->
 
<!--CRLF-->
/**
<!--CRLF-->
 * <b>function:</b> 字符编码、解码工厂类,编码过滤工厂
<!--CRLF-->
 * @author hoojo
<!--CRLF-->
 * @createDate 2012-6-26 下午01:08:50
<!--CRLF-->
 * @file CharsetCodecFactory.java
<!--CRLF-->
 * @package com.hoo.mina.code.factory
<!--CRLF-->
 * @project ApacheMiNa
<!--CRLF-->
 * @blog http://blog.csdn.net/IBM_hoojo
<!--CRLF-->
 * @email hoojo_@126.com
<!--CRLF-->
 * @version 1.0
<!--CRLF-->
 */
<!--CRLF-->
public class CharsetCodecFactory implements ProtocolCodecFactory {
<!--CRLF-->
 
<!--CRLF-->
    @Override
<!--CRLF-->
    public ProtocolDecoder getDecoder(IoSession session) throws Exception {
<!--CRLF-->
        return new CharsetDecoder();
<!--CRLF-->
    }
<!--CRLF-->
 
<!--CRLF-->
    @Override
<!--CRLF-->
    public ProtocolEncoder getEncoder(IoSession session) throws Exception {
<!--CRLF-->
        return new CharsetEncoder();
<!--CRLF-->
    }
<!--CRLF-->
}
<!--CRLF-->

解码类

package com.hoo.mina.code;
<!--CRLF-->
 
<!--CRLF-->
import java.nio.charset.Charset;
<!--CRLF-->
import org.apache.log4j.Logger;
<!--CRLF-->
import org.apache.mina.core.buffer.IoBuffer;
<!--CRLF-->
import org.apache.mina.core.session.IoSession;
<!--CRLF-->
import org.apache.mina.filter.codec.ProtocolDecoder;
<!--CRLF-->
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
<!--CRLF-->
 
<!--CRLF-->
/**
<!--CRLF-->
 * <b>function:</b> 字符解码
<!--CRLF-->
 * @author hoojo
<!--CRLF-->
 * @createDate 2012-6-26 上午11:14:18
<!--CRLF-->
 * @file CharsetDecoder.java
<!--CRLF-->
 * @package com.hoo.mina.code
<!--CRLF-->
 * @project ApacheMiNa
<!--CRLF-->
 * @blog http://blog.csdn.net/IBM_hoojo
<!--CRLF-->
 * @email hoojo_@126.com
<!--CRLF-->
 * @version 1.0
<!--CRLF-->
 */
<!--CRLF-->
public class CharsetDecoder implements ProtocolDecoder {
<!--CRLF-->
 
<!--CRLF-->
    private final static Logger log = Logger.getLogger(CharsetDecoder.class);
<!--CRLF-->
    
<!--CRLF-->
    private final static Charset charset = Charset.forName("UTF-8");    
<!--CRLF-->
    // 可变的IoBuffer数据缓冲区
<!--CRLF-->
    private IoBuffer buff = IoBuffer.allocate(100).setAutoExpand(true);
<!--CRLF-->
    
<!--CRLF-->
    @Override
<!--CRLF-->
    public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
<!--CRLF-->
        log.info("#########decode#########");
<!--CRLF-->
        
<!--CRLF-->
        // 如果有消息
<!--CRLF-->
        while (in.hasRemaining()) {
<!--CRLF-->
            // 判断消息是否是结束符,不同平台的结束符也不一样;
<!--CRLF-->
            // windows换行符(\r\n)就认为是一个完整消息的结束符了; UNIX 是\n;MAC 是\r
<!--CRLF-->
            byte b = in.get();
<!--CRLF-->
            if (b == '\n') {
<!--CRLF-->
                buff.flip();
<!--CRLF-->
                byte[] bytes = new byte[buff.limit()];
<!--CRLF-->
                buff.get(bytes);
<!--CRLF-->
                String message = new String(bytes, charset);
<!--CRLF-->
                
<!--CRLF-->
                buff = IoBuffer.allocate(100).setAutoExpand(true);
<!--CRLF-->
                
<!--CRLF-->
                // 如果结束了,就写入转码后的数据
<!--CRLF-->
                out.write(message);
<!--CRLF-->
                //log.info("message: " + message);
<!--CRLF-->
            } else {
<!--CRLF-->
                buff.put(b);
<!--CRLF-->
            }
<!--CRLF-->
        }
<!--CRLF-->
    }
<!--CRLF-->
 
<!--CRLF-->
    @Override
<!--CRLF-->
    public void dispose(IoSession session) throws Exception {
<!--CRLF-->
        log.info("#########dispose#########");
<!--CRLF-->
        log.info(session.getCurrentWriteMessage());
<!--CRLF-->
    }
<!--CRLF-->
 
<!--CRLF-->
    @Override
<!--CRLF-->
    public void finishDecode(IoSession session, ProtocolDecoderOutput out) throws Exception {
<!--CRLF-->
        log.info("#########完成解码#########");
<!--CRLF-->
    }
<!--CRLF-->
}
<!--CRLF-->

上面的decode方法是解码方法,它主要是把读取到数据中的换行符去掉。因为在mina通信协议中以换行符为结束符,如果不定义结束符那么程序会在那里一直等待下一条发送的数据。

这里用到了IoBuffer,MiNa中传输的所有二进制信息都存放在IoBuffer中,IoBuffer是对Java NIO中ByteBuffer的封装(Mina2.0以前版本这个接口也是ByteBuffer),提供了更多操作二进制数据,对象的方法,并且存储空间可以自增长,用起来非常方便;简单理解,它就是个可变长度的byte字节数组!

1. static IoBuffer allocate(int capacity,boolean useDirectBuffer)

创建IoBuffer实例,第一个参数指定初始化容量,第二个参数指定使用直接缓冲区还是JAVA 内存堆的缓存区,默认为false。

2.IoBuffer setAutoExpand(boolean autoExpand)

这个方法设置IoBuffer 为自动扩展容量,也就是前面所说的长度可变,那么可以看出长度可变这个特性默认是不开启的。

3. IoBuffer flip()

limit=position, position=0,重置mask,为了读取做好准备,一般是结束buffer操作,将buffer写入输出流时调用;这个必须要调用,否则极有可能position!=limit,导致position后面没有数据;每次写入数据到输出流时,必须确保position=limit。

4. IoBuffer clear()与IoBuffer reset()

clear:limit=capacity , position=0,重置mark;它是不清空数据,但从头开始存放数据做准备---相当于覆盖老数据。

reset就是清空数据

5. int remaining()与boolean hasRemaining()

这两个方法一般是在调用了flip方法后使用的,remaining()是返回limt-position的值!hasRemaining()则是判断当前是否有数据,返回position < limit的boolean值!

编码类

package com.hoo.mina.code;
<!--CRLF-->
 
<!--CRLF-->
import java.nio.charset.Charset;
<!--CRLF-->
import org.apache.log4j.Logger;
<!--CRLF-->
import org.apache.mina.core.buffer.IoBuffer;
<!--CRLF-->
import org.apache.mina.core.session.IoSession;
<!--CRLF-->
import org.apache.mina.filter.codec.ProtocolEncoder;
<!--CRLF-->
import org.apache.mina.filter.codec.ProtocolEncoderOutput;
<!--CRLF-->
import org.apache.mina.filter.codec.textline.LineDelimiter;
<!--CRLF-->
 
<!--CRLF-->
/**
<!--CRLF-->
 * <b>function:</b> 字符编码
<!--CRLF-->
 * @author hoojo
<!--CRLF-->
 * @createDate 2012-6-26 上午11:32:05
<!--CRLF-->
 * @file CharsetEncoder.java
<!--CRLF-->
 * @package com.hoo.mina.code
<!--CRLF-->
 * @project ApacheMiNa
<!--CRLF-->
 * @blog http://blog.csdn.net/IBM_hoojo
<!--CRLF-->
 * @email hoojo_@126.com
<!--CRLF-->
 * @version 1.0
<!--CRLF-->
 */
<!--CRLF-->
public class CharsetEncoder implements ProtocolEncoder {
<!--CRLF-->
    private final static Logger log = Logger.getLogger(CharsetEncoder.class);
<!--CRLF-->
    private final static Charset charset = Charset.forName("UTF-8");
<!--CRLF-->
    
<!--CRLF-->
    @Override
<!--CRLF-->
    public void dispose(IoSession session) throws Exception {
<!--CRLF-->
        log.info("#############dispose############");
<!--CRLF-->
    }
<!--CRLF-->
 
<!--CRLF-->
    @Override
<!--CRLF-->
    public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
<!--CRLF-->
        log.info("#############字符编码############");
<!--CRLF-->
        IoBuffer buff = IoBuffer.allocate(100).setAutoExpand(true);
<!--CRLF-->
        buff.putString(message.toString(), charset.newEncoder());
<!--CRLF-->
        // put 当前系统默认换行符
<!--CRLF-->
        buff.putString(LineDelimiter.DEFAULT.getValue(), charset.newEncoder());
<!--CRLF-->
        // 为下一次读取数据做准备
<!--CRLF-->
        buff.flip();
<!--CRLF-->
        
<!--CRLF-->
        out.write(buff);
<!--CRLF-->
    }
<!--CRLF-->
}
<!--CRLF-->

第三步:

编写IoHandler实现类代码,IoHander这里是Io读写的事件驱动类,这里的Io操作都会触发里面的事件。你所有的业务逻辑都应当在这个类中完成。

package com.hoo.mina.server.message;
<!--CRLF-->
 
<!--CRLF-->
import java.text.SimpleDateFormat;
<!--CRLF-->
import java.util.Collection;
<!--CRLF-->
import java.util.Date;
<!--CRLF-->
import org.apache.mina.core.future.CloseFuture;
<!--CRLF-->
import org.apache.mina.core.future.IoFuture;
<!--CRLF-->
import org.apache.mina.core.future.IoFutureListener;
<!--CRLF-->
import org.apache.mina.core.service.IoHandler;
<!--CRLF-->
import org.apache.mina.core.session.IdleStatus;
<!--CRLF-->
import org.apache.mina.core.session.IoSession;
<!--CRLF-->
import org.slf4j.Logger;
<!--CRLF-->
import org.slf4j.LoggerFactory;
<!--CRLF-->
 
<!--CRLF-->
/**
<!--CRLF-->
 * <b>function:</b> 处理服务器端消息
<!--CRLF-->
 * @author hoojo
<!--CRLF-->
 * @createDate 2012-6-26 下午01:12:34
<!--CRLF-->
 * @file ServerMessageHandler.java
<!--CRLF-->
 * @package com.hoo.mina.server.message
<!--CRLF-->
 * @project ApacheMiNa
<!--CRLF-->
 * @blog http://blog.csdn.net/IBM_hoojo
<!--CRLF-->
 * @email hoojo_@126.com
<!--CRLF-->
 * @version 1.0
<!--CRLF-->
 */
<!--CRLF-->
public class ServerMessageHandler implements IoHandler {
<!--CRLF-->
    
<!--CRLF-->
    private final static Logger log = LoggerFactory.getLogger(ServerMessageHandler.class);
<!--CRLF-->
    
<!--CRLF-->
    @Override
<!--CRLF-->
    public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
<!--CRLF-->
        log.info("服务器发生异常: {}", cause.getMessage());
<!--CRLF-->
    }
<!--CRLF-->
 
<!--CRLF-->
    @Override
<!--CRLF-->
    public void messageReceived(IoSession session, Object message) throws Exception {
<!--CRLF-->
        log.info("服务器接收到数据: {}", message);
<!--CRLF-->
        String content = message.toString();
<!--CRLF-->
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
<!--CRLF-->
        String datetime = sdf.format(new Date());
<!--CRLF-->
        
<!--CRLF-->
        log.info("转发 messageReceived: " + datetime + "\t" + content);
<!--CRLF-->
        
<!--CRLF-->
        // 拿到所有的客户端Session
<!--CRLF-->
        Collection<IoSession> sessions = session.getService().getManagedSessions().values();
<!--CRLF-->
        // 向所有客户端发送数据
<!--CRLF-->
        for (IoSession sess : sessions) {
<!--CRLF-->
            sess.write(datetime + "\t" + content);
<!--CRLF-->
        }
<!--CRLF-->
    }
<!--CRLF-->
 
<!--CRLF-->
    @Override
<!--CRLF-->
    public void messageSent(IoSession session, Object message) throws Exception {
<!--CRLF-->
        log.info("服务器发送消息: {}", message);
<!--CRLF-->
    }
<!--CRLF-->
 
<!--CRLF-->
    @Override
<!--CRLF-->
    public void sessionClosed(IoSession session) throws Exception {
<!--CRLF-->
        log.info("关闭当前session:{}#{}", session.getId(), session.getRemoteAddress());
<!--CRLF-->
        
<!--CRLF-->
        CloseFuture closeFuture = session.close(true);
<!--CRLF-->
        closeFuture.addListener(new IoFutureListener<IoFuture>() {
<!--CRLF-->
            public void operationComplete(IoFuture future) {
<!--CRLF-->
                if (future instanceof CloseFuture) {
<!--CRLF-->
                    ((CloseFuture) future).setClosed();
<!--CRLF-->
                    log.info("sessionClosed CloseFuture setClosed-->{},", future.getSession().getId());
<!--CRLF-->
                }
<!--CRLF-->
            }
<!--CRLF-->
        });
<!--CRLF-->
    }
<!--CRLF-->
 
<!--CRLF-->
    @Override
<!--CRLF-->
    public void sessionCreated(IoSession session) throws Exception {
<!--CRLF-->
        log.info("创建一个新连接:{}", session.getRemoteAddress());
<!--CRLF-->
        session.write("welcome to the chat room !");
<!--CRLF-->
    }
<!--CRLF-->
 
<!--CRLF-->
    @Override
<!--CRLF-->
    public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
<!--CRLF-->
        log.info("当前连接{}处于空闲状态:{}", session.getRemoteAddress(), status);
<!--CRLF-->
    }
<!--CRLF-->
 
<!--CRLF-->
    @Override
<!--CRLF-->
    public void sessionOpened(IoSession session) throws Exception {
<!--CRLF-->
        log.info("打开一个session:{}#{}", session.getId(), session.getBothIdleCount());
<!--CRLF-->
    }
<!--CRLF-->
}
<!--CRLF-->

sessionCreated:当一个新的连接建立时,由I/O processor thread调用;

sessionOpened:当连接打开是调用;

messageReceived: 当接收了一个消息时调用;

messageSent:当一个消息被(IoSession#write)发送出去后调用;

sessionIdle:当连接进入空闲状态时调用;

sessionClosed:当连接关闭时调用;

exceptionCaught:实现IoHandler的类抛出异常时调用;

一般情况下,我们最关心的只有messageReceived方法,接收消息并处理,然后调用IoSession的write方法发送出消息!(注意:这里接收到的消息都是Java对象,在IoFilter中所有二进制数据都被解码)一般情况下很少有人实现IoHandler接口,而是继承它的一个实现类IoHandlerAdapter,这样不用覆盖它的7个方法,只需要根据具体需求覆盖其中的几个方法就可以!

Iohandler的7个方法其实是根据session的4个状态值间变化来调用的:

 Connected:会话被创建并使用;

 Idle:会话在一段时间(可配置)内没有任何请求到达,进入空闲状态;

 Closing:会话将被关闭(剩余message将被强制flush);

 Closed:会话被关闭;

状态转换图如下:

clip_image004

第四步:

编写server启动类,bind端口、设置编码过程和核心业务处理器

package com.hoo.mina.server;
<!--CRLF-->
 
<!--CRLF-->
import java.io.IOException;
<!--CRLF-->
import java.net.InetSocketAddress;
<!--CRLF-->
import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
<!--CRLF-->
import org.apache.mina.core.session.IdleStatus;
<!--CRLF-->
import org.apache.mina.filter.codec.ProtocolCodecFilter;
<!--CRLF-->
import org.apache.mina.transport.socket.SocketAcceptor;
<!--CRLF-->
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
<!--CRLF-->
import com.hoo.mina.code.factory.CharsetCodecFactory;
<!--CRLF-->
import com.hoo.mina.server.message.ServerMessageHandler;
<!--CRLF-->
 
<!--CRLF-->
/**
<!--CRLF-->
 * <b>function:</b> 服务器启动类
<!--CRLF-->
 * @author hoojo
<!--CRLF-->
 * @createDate 2012-6-29 下午07:11:00
<!--CRLF-->
 * @file MinaServer.java
<!--CRLF-->
 * @package com.hoo.mina.server
<!--CRLF-->
 * @project ApacheMiNa
<!--CRLF-->
 * @blog http://blog.csdn.net/IBM_hoojo
<!--CRLF-->
 * @email hoojo_@126.com
<!--CRLF-->
 * @version 1.0
<!--CRLF-->
 */
<!--CRLF-->
public class MinaServer {
<!--CRLF-->
    
<!--CRLF-->
    private SocketAcceptor acceptor;
<!--CRLF-->
    
<!--CRLF-->
    public MinaServer() {
<!--CRLF-->
        // 创建非阻塞的server端的Socket连接
<!--CRLF-->
        acceptor = new NioSocketAcceptor();
<!--CRLF-->
    }
<!--CRLF-->
    
<!--CRLF-->
    public boolean start() {
<!--CRLF-->
        DefaultIoFilterChainBuilder filterChain = acceptor.getFilterChain();
<!--CRLF-->
        // 添加编码过滤器 处理乱码、编码问题
<!--CRLF-->
        filterChain.addLast("codec", new ProtocolCodecFilter(new CharsetCodecFactory()));
<!--CRLF-->
        
<!--CRLF-->
        /*LoggingFilter loggingFilter = new LoggingFilter();
<!--CRLF-->
        loggingFilter.setMessageReceivedLogLevel(LogLevel.INFO);
<!--CRLF-->
        loggingFilter.setMessageSentLogLevel(LogLevel.INFO);
<!--CRLF-->
        // 添加日志过滤器
<!--CRLF-->
        filterChain.addLast("loger", loggingFilter);*/
<!--CRLF-->
        
<!--CRLF-->
        // 设置核心消息业务处理器
<!--CRLF-->
        acceptor.setHandler(new ServerMessageHandler());
<!--CRLF-->
        // 设置session配置,30秒内无操作进入空闲状态
<!--CRLF-->
        acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 30);
<!--CRLF-->
        
<!--CRLF-->
        try {
<!--CRLF-->
            // 绑定端口3456
<!--CRLF-->
            acceptor.bind(new InetSocketAddress(3456));
<!--CRLF-->
        } catch (IOException e) {
<!--CRLF-->
            e.printStackTrace();
<!--CRLF-->
            return false;
<!--CRLF-->
        }
<!--CRLF-->
        return true;
<!--CRLF-->
    }
<!--CRLF-->
    
<!--CRLF-->
    public static void main(String[] args) {
<!--CRLF-->
        MinaServer server = new MinaServer();
<!--CRLF-->
        server.start();
<!--CRLF-->
    }
<!--CRLF-->
}
<!--CRLF-->

上面的代码主要完成启动参数的设置,如端口、session参数;消息核心业务处理器,这个比较关键,我们所有的业务都要在这里完成;然后就是日志、编码过滤器,我们可以对发送或接收到的消息进行处理、编码操作,在网络中传递数据都是字节流传递的,我们要获取消息必须把二进制的字节流转换的字符串来处理,所以这个也是必须的;同时你还可以对服务器添加日志过滤器,来显示日志。

这样服务器端程序就已经完成,你可以用socket或mina client等方式连接服务器,进行通信。

启动服务器,在浏览器中输入http://localhost:3456 这里的服务器绑定的端口是3456

然后你在控制台中可以看到当前浏览器的一些基本信息,如果你看到这些信息就表示你服务器代码编写没有什么问题,应该可以成功建立客户端连接。信息如下:

2012-08-01 09:55:56,046 INFO [com.hoo.mina.server.message.ServerMessageHandler:75-NioProcessor-1] - 创建一个新连接:/127.0.0.1:2542
<!--CRLF-->
2012-08-01 09:55:56,046 INFO [com.hoo.mina.code.CharsetEncoder:34-NioProcessor-1] - #############字符编码############
<!--CRLF-->
2012-08-01 09:55:56,062 INFO [com.hoo.mina.server.message.ServerMessageHandler:86-NioProcessor-1] - 打开一个session:3#0
<!--CRLF-->
2012-08-01 09:55:56,062 INFO [com.hoo.mina.server.message.ServerMessageHandler:55-NioProcessor-1] - 服务器发送消息: welcome to the chat room !
<!--CRLF-->
2012-08-01 09:55:56,062 INFO [com.hoo.mina.code.CharsetDecoder:31-NioProcessor-1] - #########decode#########
<!--CRLF-->
2012-08-01 09:55:56,062 INFO [com.hoo.mina.server.message.ServerMessageHandler:38-NioProcessor-1] - 服务器接收到数据: GET / HTTP/1.1
<!--CRLF-->
2012-08-01 09:55:56,062 INFO [com.hoo.mina.server.message.ServerMessageHandler:43-NioProcessor-1] - 转发 messageReceived: 2012-08-01 09:55:56    GET / HTTP/1.1
<!--CRLF-->
2012-08-01 09:55:56,062 INFO [com.hoo.mina.code.CharsetEncoder:34-NioProcessor-1] - #############字符编码############
<!--CRLF-->
2012-08-01 09:55:56,062 INFO [com.hoo.mina.server.message.ServerMessageHandler:38-NioProcessor-1] - 服务器接收到数据: Host: localhost:3456
<!--CRLF-->
2012-08-01 09:55:56,062 INFO [com.hoo.mina.server.message.ServerMessageHandler:43-NioProcessor-1] - 转发 messageReceived: 2012-08-01 09:55:56    Host: localhost:3456
<!--CRLF-->
2012-08-01 09:55:56,062 INFO [com.hoo.mina.code.CharsetEncoder:34-NioProcessor-1] - #############字符编码############
<!--CRLF-->
2012-08-01 09:55:56,062 INFO [com.hoo.mina.server.message.ServerMessageHandler:38-NioProcessor-1] - 服务器接收到数据: User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:14.0) Gecko/20100101 Firefox/14.0.1
<!--CRLF-->
2012-08-01 09:55:56,062 INFO [com.hoo.mina.server.message.ServerMessageHandler:43-NioProcessor-1] - 转发 messageReceived: 2012-08-01 09:55:56    User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:14.0) Gecko/20100101 Firefox/14.0.1
<!--CRLF-->
2012-08-01 09:55:56,062 INFO [com.hoo.mina.code.CharsetEncoder:34-NioProcessor-1] - #############字符编码############
<!--CRLF-->
2012-08-01 09:55:56,062 INFO [com.hoo.mina.server.message.ServerMessageHandler:38-NioProcessor-1] - 服务器接收到数据: Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
<!--CRLF-->
2012-08-01 09:55:56,062 INFO [com.hoo.mina.server.message.ServerMessageHandler:43-NioProcessor-1] - 转发 messageReceived: 2012-08-01 09:55:56    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
<!--CRLF-->
其他内容省略……
<!--CRLF-->

三、客户端编码工作

第一步:

编写客户端消息核心处理业务类型,消息处理器

package com.hoo.mina.client.message;
<!--CRLF-->
 
<!--CRLF-->
import org.apache.mina.core.service.IoHandlerAdapter;
<!--CRLF-->
import org.apache.mina.core.session.IoSession;
<!--CRLF-->
import org.slf4j.Logger;
<!--CRLF-->
import org.slf4j.LoggerFactory;
<!--CRLF-->
 
<!--CRLF-->
/**
<!--CRLF-->
 * <b>function:</b> 客户端消息处理类
<!--CRLF-->
 * @author hoojo
<!--CRLF-->
 * @createDate 2012-6-29 下午07:24:22
<!--CRLF-->
 * @file ClientMessageHandlerAdapter.java
<!--CRLF-->
 * @package com.hoo.mina.client.message
<!--CRLF-->
 * @project ApacheMiNa
<!--CRLF-->
 * @blog http://blog.csdn.net/IBM_hoojo
<!--CRLF-->
 * @email hoojo_@126.com
<!--CRLF-->
 * @version 1.0
<!--CRLF-->
 */
<!--CRLF-->
public class ClientMessageHandlerAdapter extends IoHandlerAdapter {
<!--CRLF-->
 
<!--CRLF-->
    private final static Logger log = LoggerFactory.getLogger(ClientMessageHandlerAdapter.class);
<!--CRLF-->
    
<!--CRLF-->
    public void messageReceived(IoSession session, Object message) throws Exception {
<!--CRLF-->
        String content = message.toString();
<!--CRLF-->
        log.info("client receive a message is : " + content);
<!--CRLF-->
    }
<!--CRLF-->
    
<!--CRLF-->
    public void messageSent(IoSession session , Object message) throws Exception{
<!--CRLF-->
        log.info("messageSent 客户端发送消息:" + message);
<!--CRLF-->
    }
<!--CRLF-->
    
<!--CRLF-->
    @Override
<!--CRLF-->
    public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
<!--CRLF-->
        log.info("服务器发生异常: {}", cause.getMessage());
<!--CRLF-->
    }
<!--CRLF-->
}
<!--CRLF-->

这里我们没有实现IoHandler这个接口,而是继承了IoHandlerAdapter这类,覆盖了messageReceived、messageSent这两个方法。IoHandlerAdapter是IoHandler接口的一个实现,我们这里没有必要实现IoHandler的所有方法。

第二步:

编写连接服务器的代码,设置核心消息处理器

package com.hoo.mina.client;
<!--CRLF-->
 
<!--CRLF-->
import java.net.InetSocketAddress;
<!--CRLF-->
import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
<!--CRLF-->
import org.apache.mina.core.future.CloseFuture;
<!--CRLF-->
import org.apache.mina.core.future.ConnectFuture;
<!--CRLF-->
import org.apache.mina.core.session.IoSession;
<!--CRLF-->
import org.apache.mina.filter.codec.ProtocolCodecFilter;
<!--CRLF-->
import org.apache.mina.transport.socket.SocketConnector;
<!--CRLF-->
import org.apache.mina.transport.socket.nio.NioSocketConnector;
<!--CRLF-->
import com.hoo.mina.client.message.ClientMessageHandlerAdapter;
<!--CRLF-->
import com.hoo.mina.code.factory.CharsetCodecFactory;
<!--CRLF-->
 
<!--CRLF-->
/**
<!--CRLF-->
 * <b>function:</b> mina客户端
<!--CRLF-->
 * @author hoojo
<!--CRLF-->
 * @createDate 2012-6-29 下午07:28:45
<!--CRLF-->
 * @file MinaClient.java
<!--CRLF-->
 * @package com.hoo.mina.client.message
<!--CRLF-->
 * @project ApacheMiNa
<!--CRLF-->
 * @blog http://blog.csdn.net/IBM_hoojo
<!--CRLF-->
 * @email hoojo_@126.com
<!--CRLF-->
 * @version 1.0
<!--CRLF-->
 */
<!--CRLF-->
public class MinaClient {
<!--CRLF-->
 
<!--CRLF-->
    private SocketConnector connector;
<!--CRLF-->
    private ConnectFuture future;
<!--CRLF-->
    private IoSession session;
<!--CRLF-->
 
<!--CRLF-->
    public boolean connect() {
<!--CRLF-->
 
<!--CRLF-->
        // 创建一个socket连接
<!--CRLF-->
        connector = new NioSocketConnector();
<!--CRLF-->
        // 设置链接超时时间
<!--CRLF-->
        connector.setConnectTimeoutMillis(3000);
<!--CRLF-->
        // 获取过滤器链
<!--CRLF-->
        DefaultIoFilterChainBuilder filterChain = connector.getFilterChain();
<!--CRLF-->
        // 添加编码过滤器 处理乱码、编码问题
<!--CRLF-->
        filterChain.addLast("codec", new ProtocolCodecFilter(new CharsetCodecFactory()));
<!--CRLF-->
 
<!--CRLF-->
        /*
<!--CRLF-->
        // 日志
<!--CRLF-->
        LoggingFilter loggingFilter = new LoggingFilter();
<!--CRLF-->
        loggingFilter.setMessageReceivedLogLevel(LogLevel.INFO);
<!--CRLF-->
        loggingFilter.setMessageSentLogLevel(LogLevel.INFO);
<!--CRLF-->
        filterChain.addLast("loger", loggingFilter);*/
<!--CRLF-->
 
<!--CRLF-->
        // 消息核心处理器
<!--CRLF-->
        connector.setHandler(new ClientMessageHandlerAdapter());
<!--CRLF-->
 
<!--CRLF-->
        // 连接服务器,知道端口、地址
<!--CRLF-->
        future = connector.connect(new InetSocketAddress(3456));
<!--CRLF-->
        // 等待连接创建完成
<!--CRLF-->
        future.awaitUninterruptibly();
<!--CRLF-->
        // 获取当前session
<!--CRLF-->
        session = future.getSession();
<!--CRLF-->
        return true;
<!--CRLF-->
    }
<!--CRLF-->
 
<!--CRLF-->
    public void setAttribute(Object key, Object value) {
<!--CRLF-->
        session.setAttribute(key, value);
<!--CRLF-->
    }
<!--CRLF-->
 
<!--CRLF-->
    public void send(String message) {
<!--CRLF-->
        session.write(message);
<!--CRLF-->
    }
<!--CRLF-->
 
<!--CRLF-->
    public boolean close() {
<!--CRLF-->
        CloseFuture future = session.getCloseFuture();
<!--CRLF-->
        future.awaitUninterruptibly(1000);
<!--CRLF-->
        connector.dispose();
<!--CRLF-->
        return true;
<!--CRLF-->
    }
<!--CRLF-->
 
<!--CRLF-->
    public SocketConnector getConnector() {
<!--CRLF-->
        return connector;
<!--CRLF-->
    }
<!--CRLF-->
 
<!--CRLF-->
    public IoSession getSession() {
<!--CRLF-->
        return session;
<!--CRLF-->
    }
<!--CRLF-->
}
<!--CRLF-->

第三步:

完成启动、在控制台输入你发送的内容

package com.hoo.mina.client.main;
<!--CRLF-->
 
<!--CRLF-->
import java.util.Scanner;
<!--CRLF-->
import com.hoo.mina.client.MinaClient;
<!--CRLF-->
 
<!--CRLF-->
/**
<!--CRLF-->
 * <b>function:</b> 运行客户端程序
<!--CRLF-->
 * @author hoojo
<!--CRLF-->
 * @createDate 2012-6-29 下午07:36:44
<!--CRLF-->
 * @file RunClient.java
<!--CRLF-->
 * @package com.hoo.mina.client.main
<!--CRLF-->
 * @project ApacheMiNa
<!--CRLF-->
 * @blog http://blog.csdn.net/IBM_hoojo
<!--CRLF-->
 * @email hoojo_@126.com
<!--CRLF-->
 * @version 1.0
<!--CRLF-->
 */
<!--CRLF-->
public class RunClient {
<!--CRLF-->
 
<!--CRLF-->
    public static void main(String[] args) {
<!--CRLF-->
        MinaClient client = new MinaClient();
<!--CRLF-->
        if (client.connect()) {
<!--CRLF-->
            client.send("连接服务器成功!");
<!--CRLF-->
            Scanner scanner = new Scanner(System.in);
<!--CRLF-->
            while (scanner.hasNext()) {
<!--CRLF-->
                client.send(scanner.next());
<!--CRLF-->
            }
<!--CRLF-->
        }
<!--CRLF-->
    }
<!--CRLF-->
}
<!--CRLF-->

启动服务器,运行客户端程序可以看到控制台:

2012-08-01 10:01:15,953 INFO [com.hoo.mina.code.CharsetEncoder:34-main] - #############字符编码############
<!--CRLF-->
2012-08-01 10:01:15,953 INFO [com.hoo.mina.code.CharsetDecoder:31-NioProcessor-2] - #########decode#########
<!--CRLF-->
2012-08-01 10:01:15,953 INFO [com.hoo.mina.client.message.ClientMessageHandlerAdapter:25-NioProcessor-2] - client receive a message is : welcome to the chat room !
<!--CRLF-->
2012-08-01 10:01:15,984 INFO [com.hoo.mina.client.message.ClientMessageHandlerAdapter:29-NioProcessor-2] - messageSent 客户端发送消息:连接服务器成功!
<!--CRLF-->
2012-08-01 10:01:15,984 INFO [com.hoo.mina.code.CharsetDecoder:31-NioProcessor-2] - #########decode#########
<!--CRLF-->
2012-08-01 10:01:15,984 INFO [com.hoo.mina.client.message.ClientMessageHandlerAdapter:25-NioProcessor-2] - client receive a message is : 2012-08-01 10:01:15
<!--CRLF-->

服务器控制台:

2012-08-01 10:01:15,921 INFO [com.hoo.mina.server.message.ServerMessageHandler:75-NioProcessor-2] - 创建一个新连接:/192.168.8.22:2644
<!--CRLF-->
2012-08-01 10:01:15,937 INFO [com.hoo.mina.code.CharsetEncoder:34-NioProcessor-2] - #############字符编码############
<!--CRLF-->
2012-08-01 10:01:15,937 INFO [com.hoo.mina.server.message.ServerMessageHandler:86-NioProcessor-2] - 打开一个session:1#0
<!--CRLF-->
2012-08-01 10:01:15,937 INFO [com.hoo.mina.server.message.ServerMessageHandler:55-NioProcessor-2] - 服务器发送消息: welcome to the chat room !
<!--CRLF-->
2012-08-01 10:01:15,984 INFO [com.hoo.mina.code.CharsetDecoder:31-NioProcessor-2] - #########decode#########
<!--CRLF-->
2012-08-01 10:01:15,984 INFO [com.hoo.mina.server.message.ServerMessageHandler:38-NioProcessor-2] - 服务器接收到数据: 连接服务器成功!
<!--CRLF-->
2012-08-01 10:01:15,984 INFO [com.hoo.mina.server.message.ServerMessageHandler:43-NioProcessor-2] - 转发 messageReceived: 2012-08-01 10:01:15    连接服务器成功!
<!--CRLF-->
2012-08-01 10:01:15,984 INFO [com.hoo.mina.code.CharsetEncoder:34-NioProcessor-2] - #############字符编码############
<!--CRLF-->
2012-08-01 10:01:15,984 INFO [com.hoo.mina.server.message.ServerMessageHandler:55-NioProcessor-2] - 服务器发送消息: 2012-08-01 10:01:15    连接服务器成功!
<!--CRLF-->
2012-08-01 10:01:45,984 INFO [com.hoo.mina.server.message.ServerMessageHandler:81-NioProcessor-2] - 当前连接/192.168.8.22:2644处于空闲状态:both idle
<!--CRLF-->

在客户端控制台输入聊天内容

hello,MiNaChat~!
<!--CRLF-->
2012-08-01 10:03:49,093 INFO [com.hoo.mina.code.CharsetEncoder:34-main] - #############字符编码############
<!--CRLF-->
2012-08-01 10:03:49,093 INFO [com.hoo.mina.client.message.ClientMessageHandlerAdapter:29-NioProcessor-2] - messageSent 客户端发送消息:hello,MiNaChat~!
<!--CRLF-->
2012-08-01 10:03:49,093 INFO [com.hoo.mina.code.CharsetDecoder:31-NioProcessor-2] - #########decode#########
<!--CRLF-->
2012-08-01 10:03:49,093 INFO [com.hoo.mina.client.message.ClientMessageHandlerAdapter:25-NioProcessor-2] - client receive a message is : 2012-08-01 10:03:49
<!--CRLF-->

服务器端接收到内容

2012-08-01 10:03:49,093 INFO [com.hoo.mina.code.CharsetDecoder:31-NioProcessor-2] - #########decode#########
<!--CRLF-->
2012-08-01 10:03:49,093 INFO [com.hoo.mina.server.message.ServerMessageHandler:38-NioProcessor-2] - 服务器接收到数据: hello,MiNaChat~!
<!--CRLF-->
2012-08-01 10:03:49,093 INFO [com.hoo.mina.server.message.ServerMessageHandler:43-NioProcessor-2] - 转发 messageReceived: 2012-08-01 10:03:49    hello,MiNaChat~!
<!--CRLF-->
2012-08-01 10:03:49,093 INFO [com.hoo.mina.code.CharsetEncoder:34-NioProcessor-2] - #############字符编码############
<!--CRLF-->
2012-08-01 10:03:49,093 INFO [com.hoo.mina.server.message.ServerMessageHandler:55-NioProcessor-2] - 服务器发送消息: 2012-08-01 10:03:49    hello,MiNaChat~!
<!--CRLF-->
2012-08-01 10:04:19,093 INFO [com.hoo.mina.server.message.ServerMessageHandler:81-NioProcessor-2] - 当前连接/192.168.8.22:2644处于空闲状态:both idle
<!--CRLF-->

 



作者:hoojo
出处: http://www.blogjava.net/hoojo/archive/2012/08/01/384490.html
blog:http://blog.csdn.net/IBM_hoojo
         http://hoojo.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

 

分享到:
评论

相关推荐

    apache mina实现多人聊天室

    总的来说,通过Apache Mina实现的多人聊天室项目,不仅展示了Mina如何处理网络通信,还涉及到并发编程、协议解析、过滤器链等多方面的技术知识。对于学习和理解网络编程以及Mina框架的工作原理,这是一个非常有价值...

    mina+spring实现多人聊天室程序

    Mina框架和Spring框架的结合,为开发者提供了一种高效、灵活的方式来实现这样的系统,特别是多人聊天室程序。下面我们将详细探讨如何利用这两个强大的工具来构建一个稳定且功能丰富的聊天室应用。 Mina框架,全称...

    JAVA实现XMPP客户端和服务器

    3. 聊天室和群聊:XMPP支持多用户聊天室,客户端可以加入或创建聊天室,进行多人对话。 4. 扩展服务:XMPP允许添加自定义服务,如视频通话、文件传输等,客户端和服务器需共同支持这些扩展。 六、项目实施 在“JAVA...

    chatroom.rar_ICQ/即时通讯_Java_

    在这个项目中,"多人聊天程序"表示存在一个可以同时容纳多个用户参与的交流平台。除了公共聊天室外,描述中还提到"还可以进行私人聊天",这意味着该程序不仅支持公开的群组对话,还具备一对一的私密聊天功能,这通常...

    Android毕设实战项目基于Android的医院挂号系统.zip

    【项目资源】: 适用于从基础到高级的各种项目,特别是在性能要求较高的场景中,比如操作系统开发、嵌入式编程和底层系统编程。如果您是初学者,可以从简单的控制台程序开始练习;如果是进阶开发者,可以尝试涉及硬件或网络的项目。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 # 注意 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担。 2. 部分字体以及插图等来自网络,若是侵权请联系删除。

    (源码)基于CC++的简易聊天室系统.zip

    # 基于CC++的简易聊天室系统 ## 项目简介 这是一个简单易用的聊天室练手项目,主要用于提高开发者对CC++与网络编程的理解。虽然该聊天室是运行在shell上的命令行程序,但项目致力于提升其易用性和用户体验,帮助CC++初学者和使用者摆脱命令行界面简陋、交互体验差的固有印象。此程序客户端和服务端一体,服务端对环境有数据库相关要求,客户端可能需安装dl库,同时引入了jsoncpp、sqlite3等第三方库。 ## 项目的主要特性和功能 ### 特性 客户端和服务端一体设计。 尽可能简化客户端操作,提高易用性。 运用菜单形式,减少用户手动输入操作。 对用户密码进行不可逆加密,保障信息安全。 ### 功能 支持用户注册、登录,可选择保存账号密码实现免密登录。 提供全局广播模式,支持私聊、群聊功能。 允许用户添加、删除好友,设置特别关心和黑名单。 能够创建群组、加入群组,并对群员进行管理。

    ITIL 术语和缩写中文(简体).pdf

    ITIL 术语和缩写中文

    毕业设计物联网实战项目基于ESP8266的三路86面板智能开关.zip

    【项目资源】: 物联网项目适用于从基础到高级的各种项目,特别是在性能要求较高的场景中,比如操作系统开发、嵌入式编程和底层系统编程。如果您是初学者,可以从简单的控制台程序开始练习;如果是进阶开发者,可以尝试涉及硬件或网络的项目。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 # 注意 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担。 2. 部分字体以及插图等来自网络,若是侵权请联系删除。

    毕设单片机实战项目基于 STM32F407+ESP8266+RFID 的模拟公交车刷卡收费系统(物联网版).zip

    【项目资源】: 单片机项目适用于从基础到高级的各种项目,特别是在性能要求较高的场景中,比如操作系统开发、嵌入式编程和底层系统编程。如果您是初学者,可以从简单的控制台程序开始练习;如果是进阶开发者,可以尝试涉及硬件或网络的项目。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 # 注意 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担。 2. 部分字体以及插图等来自网络,若是侵权请联系删除。

    《人工智能在智能客服领域的应用方案》

    《人工智能在智能客服领域的应用方案》:在当今数字化时代,企业与客户之间的互动日益频繁,客户服务的质量和效率成为企业竞争的关键因素之一。传统的客服模式面临着诸多挑战,如人工客服成本高昂、工作时间受限、服务质量参差不齐、难以应对大量并发的客户咨询等问题。随着人工智能技术的飞速发展,智能客服应运而生,它能够为企业提供高效、便捷、低成本的客户服务解决方案,极大地提升客户体验和企业运营效率。无论是电商、金融、电信、教育等行业,都可以通过对客服数据的分析,优化自身的业务流程和服务质量,提升企业的竞争力。

    毕业设计物联网实战项目基于云端语音识别的智能控制设备,类似于天猫精灵,小爱同学。采用的芯片为stm32f407,wm8978,esp8266。.zip

    【项目资源】: 物联网项目适用于从基础到高级的各种项目,特别是在性能要求较高的场景中,比如操作系统开发、嵌入式编程和底层系统编程。如果您是初学者,可以从简单的控制台程序开始练习;如果是进阶开发者,可以尝试涉及硬件或网络的项目。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 # 注意 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担。 2. 部分字体以及插图等来自网络,若是侵权请联系删除。

    【光电技术领域】基于单片机的音乐梦幻灯与USB转接器设计:电子琴硬件组成及仿真电路实现

    内容概要:本文档是上海理工大学光电信息与计算机工程学院学生周文龙撰写的《光电融合集成电路路技术》设计报告,指导教师为隋国荣。报告分为两个部分:一是音乐梦幻灯设计,二是USB转接器仿真设计。音乐梦幻灯设计部分,以单片机为核心,通过硬件电路和软件编程实现简易电子琴,能够自动播放音乐并在电源接通时显示LED灯,详细介绍了硬件组成、原理图、元件清单及调试过程;USB转接器仿真设计部分,旨在搭建USB转接器电路,熟悉AD和嘉立创EDA等仿真平台的操作,绘制并验证电路原理图和PCB制版图,掌握焊接工艺和电路测试,为未来从事电工电子技术行业打下基础。 适合人群:电气工程、自动化、计算机等相关专业的大专院校学生,以及对单片机应用和电子电路设计感兴趣的初学者。 使用场景及目标:①学习单片机控制电子琴的原理和实现方法,包括硬件设计和软件编程;②掌握USB转接器电路的设计流程,包括原理图绘制、仿真、PCB制版图设计和电路板焊接;③提升实际动手能力和解决实际问题的能力,为未来从事相关行业打下基础。 阅读建议:本报告详细记录了设计过程中的每一个环节,包括理论知识的应用和实际操作的经验,建议读者在阅读过程中结合实际操作,逐步理解和掌握每个步骤的具体实现方法。同时,可以参考报告中提到的相关文献和工具,加深对单片机和电子电路设计的理解。

    毕设单片机实战项目基于ESP8266的可充电天气小时钟.zip

    【项目资源】: 单片机项目适用于从基础到高级的各种项目,特别是在性能要求较高的场景中,比如操作系统开发、嵌入式编程和底层系统编程。如果您是初学者,可以从简单的控制台程序开始练习;如果是进阶开发者,可以尝试涉及硬件或网络的项目。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 # 注意 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担。 2. 部分字体以及插图等来自网络,若是侵权请联系删除。

    毕业设计物联网实战项目基于PHP7的物联网管理系统ThinkIMF ,PHP IOT FRAMEWORK.zip

    【项目资源】: 物联网项目适用于从基础到高级的各种项目,特别是在性能要求较高的场景中,比如操作系统开发、嵌入式编程和底层系统编程。如果您是初学者,可以从简单的控制台程序开始练习;如果是进阶开发者,可以尝试涉及硬件或网络的项目。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 # 注意 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担。 2. 部分字体以及插图等来自网络,若是侵权请联系删除。

    (源码)基于C语言的简单计算器.zip

    # 基于C语言的简单计算器 ## 项目简介 这是一个基于C语言的简单计算器项目,借助命令行界面为用户提供基本数学运算功能。项目运用标准C库,无需额外依赖。 ## 项目的主要特性和功能 1. 具备命令行界面,用户可在命令行输入数字和运算符,程序负责解析并执行。 2. 支持加法、减法、乘法和除法等基本数学运算。 3. 能进行错误处理,遇到不合法输入(如非数字字符或错误运算符)时,会提示用户重新输入。 4. 采用交互式设计,用户可随时退出程序或继续计算新表达式。 ## 安装使用步骤 假设用户已下载并解压了项目的源码文件,按以下步骤操作 1. 编译源代码使用C编译器(如GCC)编译项目中的 calculator.c 文件,命令为 gcc calculator.c o calculator。 2. 运行程序在终端或命令行界面中,输入 .calculator 运行程序。 3. 输入表达式按照提示输入表达式,例如 5 + 3,然后按回车键。

    VB珠宝首饰店管理系统设计(源代码+系统+开题报告+答辩PPT).zip

    摘 要 面对信息时代的机遇与挑战,利用高科技手段来提高企业的管理水平无疑是一条行之有效的途径。利用计算机管理可以最大限度的发挥准确、快捷、高效等作用, 在越来越激烈的珠宝行业中,计算机管理技术对珠宝首饰公司的服务管理提供强有力的支持。因此,利用全新的计算机网络和珠宝首饰管理系统,已成为提高珠宝首饰公司的管理效率,改进服务水准的重要手段之一。本系统应用Visual Basic 6.0 中文版开发前台,用Microsoft Access 作后台服务器,采用客户机/服务器(C/S)管理思想来对珠宝首饰进销存管理。 关键词:管理水平, 管理效率,服务水准,珠宝首饰管理系统,客户机/服务器,管理思想

    (源码)基于C语言的调试终端及格式化输出系统.zip

    # 基于C语言的调试终端及格式化输出系统 ## 项目简介 本项目是一个基于C语言的调试终端及格式化输出系统,专为嵌入式系统或其他资源受限的环境设计。它提供了类似C标准库中printf函数的功能,支持格式化输出字符串、整数、浮点数等数据类型,适用于TI的C2000 MCU tms320f280049,使用CCS V8.1 IDE进行开发。 ## 项目的主要特性和功能 1. 调试终端初始化通过DebugTerminalInit函数初始化调试终端,配置GPIO引脚和SCIA模块,实现数据回显。 2. 格式化输出提供printf、vsprintf、vsnprintf和vscnprintf函数,支持格式化输出字符串、整数、浮点数等数据类型。 3. 数字输出number函数支持多种进制和标志位的数字格式化输出。 4. 指针地址输出pointer函数支持不同类型的指针地址格式化输出。

    机械工程PT5000汽轮机滑动轴承系统模拟试验台:动态行为与振动控制研究

    内容概要:PT5000汽轮机滑动轴承系统模拟试验台是一个类似于电厂汽轮机发电机的缩小模型,旨在帮助用户获取汽轮机转子动态行为和滑动轴承油膜现象的实际经验,并研究振动控制方法。该试验台模拟两级涡轮机(低压和中压),每级转子两侧各有8个叶片,共计16个叶片。通过电机驱动而非涡轮发电机,可以进行启停机测试,识别共振现象。试验台还支持多种实验,如不平衡/现场动平衡、轴不对中实验、摩擦实验、油膜故障试验、轴颈轴承实验以及根据油压和温度进行的转子动力学试验。试验台配备了多种传感器和控制系统,包括电涡流传感器、温度传感器、压力传感器等,用于监测和记录实验数据。 适合人群:从事汽轮机设计、制造、维护的技术人员,以及相关专业的高校师生和研究人员。 使用场景及目标:①研究汽轮机转子的动态行为和滑动轴承的油膜现象;②进行振动控制方法的研究;③模拟再现油膜涡动转和油膜震荡,研究其控制条件;④进行不平衡、不对中、摩擦等常见故障的模拟和分析;⑤通过调整油压、温度和预加载力,研究轴的行为变化。 其他说明:该试验台不仅适用于教学和科研,还可用于工业领域的培训和技术验证。试验台具有丰富的配置和可选配件,可以根据具体需求进行定制。试验台的机械和电气参数详细列出,确保用户能够全面了解设备性能。

    【更新至2023年】2000-2023年中国气候政策不确定性指数(全国、省、市三个层面)

    【更新至2023年】2000-2023年中国气候政策不确定性指数数据(全国、省、市三个层面) 1.时间:2000-2023年 2.来源:使用人工审计和深度学习算法MacBERT模型,基于中国《人民日报》《光明日报》《经济日报》《环球时报》《科技日报》《中国新闻社》等6家主流报纸中的1,755,826篇文章,构建了2000年1月至2023年12月的中国全国、省份和主要城市层面的CCPU指数。研究框架包括六个部分:数据收集、清洗数据、人工审计、模型构建、指数计算与标准化以及技术验证。 3.范围:中国、省、市三个层次 4.参考文献:Ma, Y. R., Liu, Z., Ma, D., Zhai, P., Guo, K., Zhang, D., & Ji, Q. (2023). A news-based climate policy uncertainty index for China. Scientific Data, 10(1), 881. 5.时间跨度:全国层面:日度、月度、年度;省级层面:月度、年度;地级市层面:月度、年度

    Android毕设实战项目pc+android 教务询查系统.zip

    【项目资源】: 适用于从基础到高级的各种项目,特别是在性能要求较高的场景中,比如操作系统开发、嵌入式编程和底层系统编程。如果您是初学者,可以从简单的控制台程序开始练习;如果是进阶开发者,可以尝试涉及硬件或网络的项目。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 # 注意 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担。 2. 部分字体以及插图等来自网络,若是侵权请联系删除。

Global site tag (gtag.js) - Google Analytics