java --MINA篇

mina是对nio的具体实现。是目前比较高效和流行的nio框架了。

下面是对使用mina进行通讯的一个简单demo,后面再用mina写一个RPC的简单框架。

mina主要包括:
(使用的mina版本为2.0.0.M4 core,具体可见 官方网站)
mina也分服务端和客户端(这是肯定的...)

其中服务端为:NioSocketAcceptor
客户端为:NioSocketConnector

类似于Socket的服务端跟客户端Socket。除了这些用来基本通讯的之外,还有一些可以用来处理通讯中的操作类。就是在客户端和服务端的一个个filter。这些filter可以用来进行解码,编码,可以配置日志信息,可以设定序列化类型,等等。
另外为客户端和服务端都可以绑定一个IoHnadler,用来处理连接session在打开,收到信息,关闭等状态时候可以进行的动作。


现在就来使用mina进行一个简单的客户端上传文件的demo的实现:
demo实现的思想为:
客 户端跟服务端建立起来连接,客户端每次想服务端传输一定大小的文件内容。(byte的方式),然后服务端接收这些byte,将其output出来,形成文 件。客户端发送完毕后,传递一个完毕的标志,这里可以传个字符串”finish“,然后服务器收到这个结束标志,在写文件结束后,再传输个成功的标志给客 户端,(字符串”success“)然后客户端关闭连接。

服务端:
代码比较简单。

Java代码   收藏代码
  1. import java.net.InetSocketAddress;  
  2. import org.apache.mina.filter.codec.ProtocolCodecFilter;  
  3. import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory;  
  4. import org.apache.mina.filter.logging.LoggingFilter;  
  5. import org.apache.mina.transport.socket.nio.NioSocketAcceptor;  
  6.   
  7.   
  8. public class Main {  
  9.  private static final int PORT = 8080;  
  10.   
  11.  public static void main(String[] args) throws Exception {  
  12.  //服务端的实例  
  13.  NioSocketAcceptor accept=new NioSocketAcceptor();  
  14.  //添加filter,codec为序列化方式。这里为对象序列化方式,即表示传递的是对象。  
  15.  accept.getFilterChain().addLast("codec",  
  16.  new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));  
  17.                 //添加filter,日志信息  
  18.  accept.getFilterChain().addLast("logging"new LoggingFilter());  
  19.  //设置服务端的handler  
  20.  accept.setHandler(new FileUploadHandler());  
  21.  //绑定ip  
  22.  accept.bind(new InetSocketAddress(PORT));  
  23.           
  24.         System.out.println("upload  server started.");   
  25.  }  
  26. }  
 

就这样简单的完成了服务端的实现,其实可以复杂一些,其中的log跟code都可以根据需要自己来写和生成,这里只使用mina自带的。
然后是服务端的handler。

Java代码   收藏代码
  1. import java.io.BufferedOutputStream;  
  2. import java.io.File;  
  3. import java.io.FileOutputStream;  
  4. import org.apache.commons.logging.Log;  
  5. import org.apache.commons.logging.LogFactory;  
  6. import org.apache.mina.core.service.IoHandlerAdapter;  
  7. import org.apache.mina.core.session.IoSession;  
  8.   
  9. public class FileUploadHandler extends IoHandlerAdapter {  
  10.   
  11.  private BufferedOutputStream out;  
  12.   
  13.  private int count;  
  14.   
  15.  private String fileName = "D:/log/test.jpg";  
  16.   
  17.  private static final Log log = LogFactory.getLog(FileUploadHandler.class);  
  18.   
  19.   
  20.  public void sessionOpened(IoSession session) throws Exception {  
  21.  System.out.println("server open");  
  22.  }  
  23.   
  24.  public void exceptionCaught(IoSession session, Throwable cause)  
  25.  throws Exception {  
  26.  System.out.println("exception");  
  27.  session.close(true);  
  28.  super.exceptionCaught(session, cause);  
  29.  }  
  30.   
  31.  public void messageReceived(IoSession session, Object message) {  
  32.  System.out.println("server received");  
  33.   
  34.  try {  
  35.  if (message instanceof FileUploadRequest) {  
  36.                  //FileUploadRequest 为传递过程中使用的DO。  
  37.  FileUploadRequest request = (FileUploadRequest) message;  
  38.  System.out.println(request.getFilename());  
  39.  if (out == null) {  
  40.  //新建一个文件输入对象BufferedOutputStream,随便定义新文件的位置  
  41.  out = new BufferedOutputStream(new FileOutputStream(  
  42.  "D:/log/" + request.getFilename()));  
  43.  out.write(request.getFileContent());  
  44.  } else {  
  45.  out.write(request.getFileContent());  
  46.  }  
  47.  count += request.getFileContent().length;  
  48.   
  49.  } else if (message instanceof String) {  
  50.  if (((String)message).equals("finish")) {  
  51.  System.out.println("size is"+count);  
  52.  //这里是进行文件传输后,要进行flush和close否则传递的文件不完整。  
  53.  out.flush();  
  54.  out.close();  
  55.  //回执客户端信息,上传文件成功  
  56.  session.write("success");  
  57.  }  
  58.  }  
  59.   
  60.  } catch (Exception e) {  
  61.  e.printStackTrace();  
  62.  }  
  63.  }  
  64.   
  65.  public void sessionClosed(IoSession session) throws Exception {  
  66.  System.out.println("server session close");  
  67.  }  
  68. }  
 

所有的handler都要继承IoHandlerAdapter,可以查看IoHandlerAdapter,其包括几个关于session状态的方法。按需进行重载即可。

然后就是公用的用来传输的DO:FileUploadRequest简单的POJO

Java代码   收藏代码
  1. import java.io.Serializable;  
  2.   
  3. public class FileUploadRequest implements Serializable {  
  4.  private String hostname;  
  5.  private String filename;  
  6.  private byte[] fileContent;  
  7.   
  8.  public String getHostname() {  
  9.  return hostname;  
  10.  }  
  11.   
  12.  public void setHostname(String hostname) {  
  13.  this.hostname = hostname;  
  14.  }  
  15.   
  16.  public String getFilename() {  
  17.  return filename;  
  18.  }  
  19.   
  20.  public void setFilename(String filename) {  
  21.  this.filename = filename;  
  22.  }  
  23.   
  24.  public byte[] getFileContent() {  
  25.  return fileContent;  
  26.  }  
  27.   
  28.  public void setFileContent(byte[] fileContent) {  
  29.  this.fileContent = fileContent;  
  30.  }  
  31. }  
 

接下来看下客户端的实现,也很简单:

Java代码   收藏代码
  1. import java.io.File;  
  2. import java.io.FileInputStream;  
  3. import java.io.IOException;  
  4. import java.net.InetSocketAddress;  
  5. import nio.upload.server.FileUploadRequest;  
  6. import org.apache.mina.core.future.ConnectFuture;  
  7. import org.apache.mina.core.session.IoSession;  
  8. import org.apache.mina.filter.codec.ProtocolCodecFilter;  
  9. import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory;  
  10. import org.apache.mina.filter.logging.LoggingFilter;  
  11. import org.apache.mina.transport.socket.nio.NioSocketConnector;  
  12.   
  13. public class MainClient {  
  14.   
  15.  private static final int PORT = 8080;  
  16.   
  17.  /** 
  18.   * @param args 
  19.   * @throws IOException 
  20.   */  
  21.  public static void main(String[] args) throws Exception {  
  22.  //客户端的实现  
  23.  NioSocketConnector connector = new NioSocketConnector();  
  24.  connector.getFilterChain().addLast("codec",  
  25.  new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));  
  26.  connector.getFilterChain().addLast("logging"new LoggingFilter());  
  27.  FileUploadClientHandler h = new FileUploadClientHandler();  
  28.  connector.setHandler(h);  
  29.  //本句需要加上,否则无法调用下面的readFuture来从session中读取到服务端返回的信息。  
  30.  connector.getSessionConfig().setUseReadOperation(true);  
  31.   
  32.  ConnectFuture cf = connector.connect(new InetSocketAddress("localhost",  
  33.  PORT));  
  34.   
  35.  IoSession session;  
  36.  //等待连接成功  
  37.  cf.awaitUninterruptibly();  
  38.  session = cf.getSession();  
  39.   
  40.  System.out.println("client send begin");  
  41.    
  42.  //传递文件开始  
  43.  String fileName = "test.jpg";  
  44.  FileInputStream fis = new FileInputStream(new File(fileName));  
  45.  byte[] a = new byte[1024 * 4];  
  46.  FileUploadRequest request = new FileUploadRequest();  
  47.  request.setFilename(fileName);  
  48.  request.setHostname("localhost");  
  49.  while (fis.read(a, 0, a.length) != -1) {  
  50.  request.setFileContent(a);  
  51.  //像session中写入信息供服务端获得  
  52.  session.write(request);  
  53.  }  
  54.  //发送完成的标志  
  55.  session.write(new String("finish"));  
  56.   
  57.  System.out.println("client send finished and wait success");  
  58.  //接上面来取得服务端的信息  
  59.  Object result = session.read().awaitUninterruptibly().getMessage();  
  60.  if (result.equals("success")) {  
  61.  System.out.println("success!");  
  62.  //关闭客户端  
  63.  connector.dispose();  
  64.  }  
  65.  }  
  66. }  
 

客户端handler的实现。

Java代码   收藏代码
  1. import org.apache.mina.core.service.IoHandlerAdapter;  
  2. import org.apache.mina.core.session.IoSession;  
  3.   
  4.   
  5. public class FileUploadClientHandler extends IoHandlerAdapter {  
  6.   
  7.  public void sessionOpened(IoSession session) throws Exception {  
  8.  System.out.println("client open");  
  9.  }  
  10.   
  11.  public void sessionClosed(IoSession session) throws Exception {  
  12.  System.out.println("client session close");  
  13.  }  
  14.   
  15.  public void messageReceived(IoSession session, Object message)  
  16.  throws Exception {  
  17.  System.out.println("thr result is" + message);  
  18.  }  
  19. }  
 

心得:
注意其中关于文件的操作,outPutStream在传输完之后要进行flush跟close,因此需要客户端给一个结束的标志,才能进行判断。mina的结构也比较清晰,深层次的以后再研究。

PS:
有个小小疑问:在客户端对session不停的write之后,服务端在接收的时候是能保证按照我写入的顺序来读取的吗。估计这其中的传递用的是一个能同步的队列。这样才能保证客户端写的顺序跟服务端读的顺序一致。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值