使用Mina框架开发 QQ Android 客户端
Apache MINA是一个网络应用程序框架,用来帮助用户简单地开发高性能和高可靠性的网络应用程序。它提供了一个通过Java NIO在不同的传输例如TCP/IP和UDP/IP上抽象的事件驱动的异步API。
Apache MINA 也称为:
● NIO 框架库
● 客户端服务器框架库
● 一个网络套接字库
MINA虽然简单但是仍然提供了全功能的网络应用程序框架:
● 为不同的传输类型提供了统一的API:
○ 通过Java NIO提供TCP/IP 和 UDP/IP支持
○ 通过RXTX提供串口通讯(RS232)
○ In-VM管道通讯
○ 你能实现你自己的API!
● 过滤器作为一个扩展特性; 类似Servlet过滤器
● 低级和高级的API:
○ 低级: 使用字节缓存(ByteBuffers)
○ 高级: 使用用户定义的消息对象(objects)和编码(codecs)
● 高度定制化线程模型:
○ 单线程
○ 一个线程池
○ 一个以上的线程池(也就是SEDA)
● 使用Java 5 SSL引擎提供沙盒(Out-of-the-box) SSL · TLS · StartTLS支持
● 超载保护和传输流量控制
● 利用模拟对象进行单元测试
● JMX管理能力
● 通过StreamIoHandler提供基于流的I/O支持
● 和知名的容器(例如PicoContainer、Spring)集成
● 从Netty平滑的迁移到MINA, Netty是MINA的前辈。
MINA 基本类的描述 :
IoAccepter 相当于网络应用程序中的服务器端
IoConnector 相当于客户端
IoSession 当前客户端到服务器端的一个连接实例
IoHandler 业务处理逻辑
IoFilter 过滤器用于悬接通讯层接口与业务层接口
要编写和运行一个基于Apache MINA 2.0的程序,需要JDK 5.0以上版本,
下面看一个domo:
准备工作:
mina-core-2.0.0-M6.jar
slf4j-api-1.5.2.jar
在官网下载到mina,找出这几个jar,添加到项目,
服务端的代码:
- public class MainFrame {
- private static final int PORT=5469;
- public static void main(String[] args) throws Exception{
- IoAcceptor acceptor=new NioSocketAcceptor();
- IoFilter filter=new ProtocolCodecFilter(new TextLineCodecFactory());
- acceptor.getFilterChain().addLast("vestigge", filter);
- acceptor.setHandler(new ServerHandler());
- acceptor.bind(new InetSocketAddress(PORT));
- System.out.println( "服务器正在监听端口" + PORT +"...");
- }
- }
其中new ServerHandler()传入的是实现了IoHandler接口的类,代码如下:
- public class ServerHandler extends IoHandlerAdapter {
- @Override
- public void messageReceived(IoSession session, Object message)
- throws Exception {
- System.out.println("收到客户端消息:" + message.toString());
- }
- @Override
- public void exceptionCaught(IoSession session, Throwable cause)
- throws Exception {
- System.out.println("服务器出现异常:" +cause);
- }
- }
重写了父类中的messageReceived()和exceptionCaught()
一般在messageReceived()中对客户端的请求进行业务,逻辑处理
下面在命令行用telnet测试一下,
如果是win 7没有telnet,找到“打开或关闭Windows功能” ,找到telnet客户端和telnet服务端,勾选即可,
在命令行下输入telnet 127.0.0.1 5469
然后再telnet窗口中输入几个字符回车,在控制台可以看到服务器成功收到了消息:
上节中通过一个简单的例子,对Mina框架有了大体的了解,在上节的基础上,看看 怎样实现客户端与服务端的通信,
废话不多说了,直接看代码:
- public class Test {
- public static void main(String[] args) throws Exception{
- SocketConnector connector = new NioSocketConnector();
- IoFilter filter = new ProtocolCodecFilter(new TextLineCodecFactory());
- connector.getFilterChain().addLast("vestigge", filter);
- SocketAddress soketAddress = new InetSocketAddress("127.0.0.1", 5469);
- connector.setHandler(new ClientHandler());
- ConnectFuture future= connector.connect(soketAddress);
- future.join();
- if (!future.isConnected()) {
- System.out.println("连接服务器失败");
- return;
- }
- future.getSession().write("hello");
- }
- }
可以看到代码与服务器端的代码很像,也是非常的简单,这就是框架的好处,不用再重复发明轮子,省了不少事,
- public class ClientHandler extends IoHandlerAdapter {
- public void messageReceived(IoSession arg0, Object message) throws Exception {
- System.out.println("收到服务器消息:" + message.toString());
- }
- public void exceptionCaught(IoSession arg0, Throwable arg1)
- throws Exception {
- }
- }
效果演示:
登陆界面的文章 http://www.linuxidc.com/Linux/2012-11/73437.htm
就不在重复了,直接看登陆的代码,
用Mina传递字符串上节已经看过了,要实现传递对象,也非常简单,只需要修改一下过滤器:
chain.addLast("codec", new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));
在Android客户端,登陆的Activity中:
- public class LoginActivity extends Activity{
- private EditText accountEditText;
- private EditText passwordEditText;
- private CheckBox remeberCheckBox;
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.activity_login);
- accountEditText=(EditText) findViewById(R.id.login_account);
- passwordEditText=(EditText) findViewById(R.id.login_password);
- remeberCheckBox=(CheckBox) findViewById(R.id.login_remember);
- findViewById(R.id.login_login).setOnClickListener(new OnClickListener(){
- public void onClick(View v) {
- if(accountEditText.getText().toString().equals("") ||
- passwordEditText.getText().toString().equals("")){
- Toast.makeText(LoginActivity.this, "账号或密码不能为空!", Toast.LENGTH_SHORT).show();
- }else{
- User user=new User();
- user.setAccount(Integer.parseInt(accountEditText.getText().toString()));
- user.setPassword(passwordEditText.getText().toString());
- user.setOperation(VQMessageType.LOGIN);
- boolean b=new VQClient().sendLoginInfo(user);
- //如果登录成功
- if(b){
- Toast.makeText(LoginActivity.this, "登陆成功!", Toast.LENGTH_SHORT).show();
- startActivity(new Intent(LoginActivity.this,MainActivity.class));
- }else{
- Toast.makeText(LoginActivity.this, "连接超时,登陆失败!", Toast.LENGTH_SHORT).show();
- }
- }
- }
- });
- }
- }
可以看到会调用VQClient这个类中的方法去发送登陆请求,VQClient的实现:
- public class VQClient {
- private static int PORT=5469;
- public boolean sendLoginInfo(User u){
- boolean b=false;
- System.setProperty("java.net.preferIPv6Addresses", "false");//2.2会有ipv6的问题,
- SocketConnector connector = new NioSocketConnector();
- connector.setConnectTimeoutMillis(300000);
- DefaultIoFilterChainBuilder chain=connector.getFilterChain();
- chain.addLast("codec", new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));
- SocketSessionConfig cfg = connector.getSessionConfig();
- cfg.setUseReadOperation(true);
- IoSession session = connector.connect(new InetSocketAddress("10.0.2.2", PORT))
- .awaitUninterruptibly().getSession();
- //发送并等待完成
- session.write(u).awaitUninterruptibly();
- //接收
- ReadFuture readFuture = session.read();
- //接收超时
- if (readFuture.awaitUninterruptibly(30000,TimeUnit.SECONDS)) {
- VQMessage message = (VQMessage) readFuture.getMessage();
- //如果是登陆成功的信息
- if(message.getType().equals(VQMessageType.SUCCESS)){
- b= true;
- }
- } else {
- b= false;
- }
- //断开连接
- session.close(true);
- session.getService().dispose();
- return b;
- }
- }
然后服务器端变化不大,在收到登陆请求后,会查询数据库,返回一个信息,来表明登陆成功或者失败。
- public void messageReceived(IoSession session, Object message)
- throws Exception {
- User user=(User) message;
- if(user.getOperation().equals(VQMessageType.LOGIN)){
- //操作数据库
- boolean b=new UserDao().login(user.getAccount(), user.getPassword());
- if(b){
- System.out.println(">> ["+user.getAccount()+"] 上线了");
- //告诉客户端登陆成功
- VQMessage m=new VQMessage();
- m.setType(VQMessageType.SUCCESS);
- session.write(m);
- }
- }
- }
最后附上测试效果:
使用Mina框架开发 QQ Android 客户端的更多相关文章
- GPS部标平台的架构设计(三) 基于struts+spring+hibernate+ibatis+quartz+mina框架开发GPS平台
注意,此版本是2014年研发的基于Spring2.5和Struts2的版本,此版本的源码仍然销售,但已不再提供源码升级的服务,因为目前我们开发的主流新版本是2015-2016年近一年推出的基于spri ...
- SUI Mobile框架开发,android、ios表单遇到的问题
1.页面添加区域滚动,滚动区域内元素事件无效问题 解决方法: <script type="text/javascript" charset="utf-8" ...
- 【FastDev4Android框架开发】RecyclerView完全解析之下拉刷新与上拉加载SwipeRefreshLayout(三十一)
转载请标明出处: http://blog.csdn.net/developer_jiangqq/article/details/49992269 本文出自:[江清清的博客] (一).前言: [好消息] ...
- struts2中获取request、response,与android客户端进行交互(文件传递给客户端)
用struts2作为服务器框架,与android客户端进行交互需要得到request.response对象. struts2中获取request.response有两种方法. 第一种:利用Servle ...
- WebService系列二:使用JDK和CXF框架开发WebService
一.使用JDK开发WebService 服务端程序创建: 1.新建一个JDK开发webservice的服务端maven项目JDKWebServiceServer 2. 定义一个接口,使用@WebSer ...
- Mina框架的学习笔记——Android客户端的实现
Apache MINA(Multipurpose Infrastructure for Network Applications) 是 Apache 组织一个较新的项目,它为开发高性能和高可用性的网络 ...
- 基于Java Mina框架的部标808服务器设计和开发
在开发部标GPS平台中,部标808GPS服务器是系统的核心关键,决定了部标平台的稳定性和行那个.Linux服务器是首选,为了跨平台,开发语言选择Java自不待言. 我们为客户开发的部标服务器基于Min ...
- Android Mina框架的学习笔记
Apache MINA(Multipurpose Infrastructure for Network Applications) 是 Apache 组织一个较新的项目,它为开发高性能和高可用性的网络 ...
- 基于Java Mina框架的部标jt808服务器设计和开发
在开发部标GPS平台中,部标jt808GPS服务器是系统的核心关键,决定了部标平台的稳定性和行那个.Linux服务器是首选,为了跨平台,开发语言选择Java自不待言.需要购买jt808GPS服务器源码 ...
随机推荐
- 微信公众平台开发(一) ——实现URL接入
一.填写服务器配置 登录微信公众平台,点击开发者中心,点击“修改配置”按钮,填写服务器地址(URL).Token和EncodingAESKey.URL是开发者用来接收微信消息和事件的接口URL.Tok ...
- js获取当前事件键盘按钮
用户名:<input type="text" name="username" id="username"><br /> ...
- 总结:如何获取同一个DIV里的多个不同子标签的值,并赋值给input?
这个问题说起来简单,但对于新手来说,也着实卡了好久,并且我在网上搜了好久没能找到合适的答案, 于是去博问问了一下,得到许多大神们的帮助与回答,接下来我就总结一下能够实现这个效果的几种方法,既为了自己更 ...
- 武汉科技大学ACM :1008: 华科版C语言程序设计教程(第二版)习题6.14
Problem Description 输入一个八进制的字符串,将它转换成等价的十进制字符串,用pringf的%s格式输出. Input 首先输入一个正整数t,表示有t组测试数据(1<= t & ...
- 如何在Eclipse中给main方法加参数
在main方法中有一个args参数,那么如何给args参数赋值呢? public class TestMain { public static void main(String[] args) { f ...
- d023: 各位数字之和
内容: 求输入的一个整数的各位数字之和 输入说明: 一行一个整数 输出说明: 一个整数 输入样例: 2147483646 输出样例 : 45 #include <stdio.h> int ...
- C#中out的一种用法
1.当希望方法返回多个值时,声明out 方法很有用. 这样使方法可以有选择地返回值. using System; using System.Collections.Generic; using Sys ...
- The given object has a null identifier解决之法
<input type="hidden" name="memberPermission.id" value="${memb ...
- Ftp协议Socket实现
原来用WebRequest来传输文件,被人鄙视了.就弄个Socket版的,支持Active,Passive模式. 带事件日志,有时间的人可以拿去做C#版的flashfxp. public class ...
- Chrome下的语音控制框架MyVoix.js使用篇(四)
在上一篇博文中,我为大家介绍了myvoix.js中的smart learning模块,以及何如使用该功能.(myvoix.js的源码地址会在每一篇文章末尾放出) 文本将拓展 Chrome下的语音控制框 ...