精华内容
下载资源
问答
  • Android Mina 与Linux TCP通信-1

    千次阅读 2016-04-21 22:23:19
    Android的TCP框架有两框架可以选择Netty和Mina,为此我还专门看过博客,虽然并没有什么实质性进展。。大家对Netty比较看好,虽然这两都是一作者,于是使用Netty,资料其少无比!!英文的也不。。于是弃坑了...

    这是一个什么系列

    最近做了一个IM的项目,客户端是Android,服务器是Linux,不算什么新颖,但是我在爬坑的过程中总结的问题能够给你一个知道,使你迅速定位问题,当然我只是一个研究生,如果你是大牛请多指教。
    服务器的文章写过一篇,但是一直没有时间继续写,最近有需要写客户端还有就是我在做这个项目的一些思考。最近加把劲争取每周都能更新一篇吧。

    写在前面

    之前用Linux写过一个服务器,有这篇博客
    https://github.com/wsrspirit/Linux_Server_Reactor
    现在开始接手Android。
    通信协议基本已经确定,通信协议会单独写博客,这个需要我完完全全搞定通信再写,目前也在摸着石头过河。
    下面就是通信了。Android的TCP框架有两个框架可以选择Netty和Mina,为此我还专门看过博客,虽然并没有什么实质性进展。。大家对Netty比较看好,虽然这两个都是一个作者,于是使用Netty,资料其少无比!!英文的也不多。。于是弃坑了,Android Mina还是较多的。没办法赶进度,不能慢慢啃了。。

    配置

    Mina开发非常简单,首先是包

    compile 'org.slf4j:slf4j-android:1.7.7'
    compile 'org.apache.mina:mina-core:2.0.4'

    如果你出现了Failed to load class “org.slf4j.impl.StaticLoggerBinder”说明你没有加载slf4j的依赖。但是如果你gradle编译出现了依赖重复,

    com.android.dex.DexException: Multiple dex files define Lorg/slf4j/ILoggerFactory;

    下面的网站帮助你~
    http://blog.csdn.net/hyr83960944/article/details/41825087

    大端小端?

    这个是要最先考虑的,Linux没什么说的肯定是小端了,Java和网络流是大端,这就需要对应了。写个测试
    Java:

    boolean b = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;

    C测试的思路就是一个union中一个int和char然后int=1 判断char
    Linux需要使用小端数据,所以网络数据需要转换。ntohl是Linux提供的方法
    同时网络数据需要时大端数据,Linux在发送的时候还需要再转换。htonl是Linux提供的方法
    http://linux.die.net/man/3/htons

    如果你传了一个很小的id,结果对面解析成了很大的数字,那么基本就是大端小端的问题了。这个问题会单独写一篇博客的。

    写代码

    然后就可以愉快的编代码了,Mina非常简单
    首先写个Thread

    public class MinaThread implements Runnable{
        private IoSession session = null;
    
        @Override
        public void run() {
            // TODO Auto-generated method stub
            Log.d("TEST", "客户端链接开始...");
            IoConnector connector = new NioSocketConnector();
    
            //设置链接超时时间
            connector.setConnectTimeoutMillis(3000);
            //添加过滤器
            connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory()));
            connector.setHandler(new MinaClientHandler());
    
            try{
                ConnectFuture future = connector.connect(new InetSocketAddress(PathUtil.IP,PathUtil.PORT));//创建链接
                future.awaitUninterruptibly();// 等待连接创建完成
                session = future.getSession();//获得session
                MessageEntity messageEntity = new MessageEntity();
                messageEntity.setDesId(PackageFlag.REGISTE_USER);
                Gson gson = new Gson();
                session.write(gson.toJson(messageEntity));
            }catch (Exception e){
                Log.d("TEST","客户端链接异常...");
                e.printStackTrace();
            }
    
            CloseFuture closeFuture = session.getCloseFuture();
            closeFuture.awaitUninterruptibly();
    //                session.getCloseFuture().awaitUninterruptibly();//等待连接断开
            Log.d("TEST", "客户端断开...");
            connector.dispose();
        }
    
    }

    然后再写个handler

    public class MinaClientHandler extends IoHandlerAdapter {
        private static final String TAG = "IM_Client_Core";
        @Override
        public void exceptionCaught(IoSession session, Throwable cause)
                throws Exception {
            Log.d("TEST", "客户端发生异常");
            super.exceptionCaught(session, cause);
        }
    
        @Override
        public void sessionCreated(IoSession session) throws Exception {
            Log.d(TAG,"sessionCreated");
            super.sessionCreated(session);
        }
    
        @Override
        public void sessionOpened(IoSession session) throws Exception {
            Log.d(TAG,"sessionOpened");
            super.sessionOpened(session);
        }
    
        @Override
        public void sessionClosed(IoSession session) throws Exception {
            Log.d(TAG,"sessionClosed");
            super.sessionClosed(session);
        }
    
        @Override
        public void messageReceived(IoSession session, Object message)
                throws Exception {
    
            String msg = message.toString();
            System.out.println("客户端接收到的信息为:" + msg);
            Log.d("TEST","客户端接收到的信息为:" + msg);
            super.messageReceived(session, message);
        }
    
        @Override
        public void messageSent(IoSession session, Object message) throws Exception {
            // TODO Auto-generated method stub
            super.messageSent(session, message);
        }
    }

    App发送数据没什么问题,服务器收到了,但是没想到客户端收不到服务器的回复,也就是MinaClientHandler的messageReceived没有执行!奇怪的是sessionCreated和sessionOpened也不打印日志,我一下慌了,以为Log没有配置正确,查之后slf4j是一个接口型日志,而Android自带Log的实现,应该不是这里的问题,关键是没有execption啊!这个问题解决的有点呵呵,我把魅族换成了小米测试,出现了Log消息。。沃日!

    再抓包,发现包是发过去了,抓包这个自己搜一个用的顺手的就好了~

    再搜索!于是找到了一个靠谱的
    http://stackoverflow.com/questions/2735370/apache-mina-nio-connector-help

    but the TextLineDecoder created by TextLineCodecFactory will be looking for (by default) a ‘\r’ (0x0d) or ‘\n’ (0x0a) to end the line and generate the completed message to be handled by your IoHandlerAdapter.

    这。。。居然是这么flush缓冲区的,我在Iosession方法中没找到flush方法啊,好吧,于是在服务器返回数据中加入’\n’
    于是又有了:Caused by: java.nio.charset.MalformedInputException并且还是没有收到信息,查
    http://my.oschina.net/gs80140/blog/209700
    我想大概意思我懂了,就是应该是在’\n’和包内容结束中间有空隙(我确实留了空袭),于是直接在包最后紧贴着加上’\n’。ok终于收到了。

    优化

    这个问题还是因为使用了Mina的Encoder类,找不到结束位置,所以还是自己重写这个方法好一些,官网的例子如下~
    https://mina.apache.org/mina-project/userguide/ch9-codec-filter/ch9-codec-filter.html

    这只是系列的第一个博客,希望能有机会把客户端和服务器都写的好一点,服务器已经上传github。服务器的博客也一直没有时间更新。。。最近好忙,心情也不好 = =b(投了百度的实习居然连笔试都不给。。悲剧)
    https://github.com/wsrspirit/Linux_Server_Reactor

    愿一切顺利吧

    展开全文
  • 收发两端(客户端和服务器端)都要有一一成对的socket,因此,发送端为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行...

    一 tcp与udp

    1.1 tcp与udp的概念

    TCP(transport control protocol,传输控制协议)是面向连接的,面向流的,提供高可靠性服务。收发两端(客户端和服务器端)都要有一一成对的socket,因 此,发送端为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包。这样,接收端,就难于分辨出来了,必须提供科学的拆包机制。即面向流的通信是无消息保护边界的。

    udp: 用户数据报协议)是无连接的,面向消息的,提供高效率服务。不会使用块的合并优化算法,, 由于UDP支持的是一对多的模式,所以接收端的skbuff(套接字缓冲区)采用了链式结构来记录每一个到达的UDP包,在每个UDP包中就有了消息头(消息来源地址,端口等信息),这样,对于接收 端来说,就容易进行区分处理了。 即面向消息的通信是有消息保护边界的。

    1.2 tcp的粘包,半包

     1.3 原因

     1.4 解决办法

    1.定长的方式:数据不够,用数据符号填充,在解包的时候,判断满足长度解包。

    2.特殊字符开头和结尾,作为界定范围。

    3.消息报文:制定固定格式:头部(长度,版本号)+消息体

    展开全文
  • 接口是服务端IoAcceptor、客户端IoConnector 的抽象,提供IO 服务和管理IoSession 的功能,它有如下几常用的方法: A. TransportMetadata getTransportMetadata(): 这方法获取传输方式的元数据描述信息...
    (1.)IoService:
    
    这个接口是服务端IoAcceptor、客户端IoConnector 的抽象,提供IO 服务和管理IoSession
    的功能,它有如下几个常用的方法:
    A. TransportMetadata getTransportMetadata():
    这个方法获取传输方式的元数据描述信息,也就是底层到底基于什么的实现,譬如:nio、
    apr 等。
    B. void addListener(IoServiceListener listener):
    这个方法可以为IoService 增加一个监听器,用于监听IoService 的创建、活动、失效、空
    闲、销毁,具体可以参考IoServiceListener 接口中的方法,这为你参与IoService 的生命
    周期提供了机会。
    C. void removeListener(IoServiceListener listener):
    这个方法用于移除上面的方法添加的监听器。
    D. void setHandler(IoHandler handler):
    这个方法用于向IoService 注册IoHandler,同时有getHandler()方法获取Handler。
    E. Map<Long,IoSession> getManagedSessions():
    这个方法获取IoService 上管理的所有IoSession,Map 的key 是IoSession 的id。
    F. IoSessionConfig getSessionConfig():
    这个方法用于获取IoSession 的配置对象,通过IoSessionConfig 对象可以设置Socket 连
    接的一些选项。

    (2.)IoAcceptor:
    这个接口是TCPServer 的接口,主要增加了void bind()监听端口、void unbind()解除对
    套接字的监听等方法。这里与传统的JAVA 中的ServerSocket 不同的是IoAcceptor 可以多
    次调用bind()方法(或者在一个方法中传入多个SocketAddress 参数)同时监听多个端口。

    (3.)IoConnector:
    这个接口是TCPClient 的接口, 主要增加了ConnectFuture connect(SocketAddress
    remoteAddress,SocketAddress localAddress)方法,用于与Server 端建立连接,第二个参
    数如果不传递则使用本地的一个随机端口访问Server 端。这个方法是异步执行的,同样的,
    也可以同时连接多个服务端。

    (4.)IoSession:
    这个接口用于表示Server 端与Client 端的连接,IoAcceptor.accept()的时候返回实例。
    这个接口有如下常用的方法:
    A. WriteFuture write(Object message):
    这个方法用于写数据,该操作是异步的。
    B. CloseFuture close(boolean immediately):
    这个方法用于关闭IoSession,该操作也是异步的,参数指定true 表示立即关闭,否则就
    在所有的写操作都flush 之后再关闭。
    C. Object setAttribute(Object key,Object value):
    这个方法用于给我们向会话中添加一些属性,这样可以在会话过程中都可以使用,类似于
    HttpSession 的setAttrbute()方法。IoSession 内部使用同步的HashMap 存储你添加的自
    定义属性。
    D. SocketAddress getRemoteAddress():
    这个方法获取远端连接的套接字地址。
    E. void suspendWrite():
    这个方法用于挂起写操作,那么有void resumeWrite()方法与之配对。对于read()方法同
    样适用。
    F. ReadFuture read():
    这个方法用于读取数据, 但默认是不能使用的, 你需要调用IoSessionConfig 的
    setUseReadOperation(true)才可以使用这个异步读取的方法。一般我们不会用到这个方法,
    因为这个方法的内部实现是将数据保存到一个BlockingQueue,假如是Server 端,因为大
    量的Client 端发送的数据在Server 端都这么读取,那么可能会导致内存泄漏,但对于
    Client,可能有的时候会比较便利。
    G. IoService getService():
    这个方法返回与当前会话对象关联的IoService 实例。

    关于TCP连接的关闭:
    无论在客户端还是服务端,IoSession 都用于表示底层的一个TCP 连接,那么你会发现无论
    是Server 端还是Client 端的IoSession 调用close()方法之后,TCP 连接虽然显示关闭, 但
    主线程仍然在运行,也就是JVM 并未退出,这是因为IoSession 的close()仅仅是关闭了TCP
    的连接通道,并没有关闭Server 端、Client 端的程序。你需要调用IoService 的dispose()
    方法停止Server 端、Client 端。

    (5.)IoSessionConfig:
    这个方法用于指定此次会话的配置,它有如下常用的方法:
    A. void setReadBufferSize(int size):
    这个方法设置读取缓冲的字节数,但一般不需要调用这个方法,因为IoProcessor 会自动调
    整缓冲的大小。你可以调用setMinReadBufferSize()、setMaxReadBufferSize()方法,这
    样无论IoProcessor 无论如何自动调整,都会在你指定的区间。
    B. void setIdleTime(IdleStatus status,int idleTime):
    这个方法设置关联在通道上的读、写或者是读写事件在指定时间内未发生,该通道就进入空
    闲状态。一旦调用这个方法,则每隔idleTime 都会回调过滤器、IoHandler 中的sessionIdle()
    方法。
    C. void setWriteTimeout(int time):
    这个方法设置写操作的超时时间。
    D. void setUseReadOperation(boolean useReadOperation):
    这个方法设置IoSession 的read()方法是否可用,默认是false。
    _______________________________________________________________________________
    (6.)IoHandler:
    这个接口是你编写业务逻辑的地方,从上面的示例代码可以看出,读取数据、发送数据基本
    都在这个接口总完成,这个实例是绑定到IoService 上的,有且只有一个实例(没有给一个
    IoService 注入一个IoHandler 实例会抛出异常)。它有如下几个方法:
    A. void sessionCreated(IoSession session):
    这个方法当一个Session 对象被创建的时候被调用。对于TCP 连接来说,连接被接受的时候
    调用,但要注意此时TCP 连接并未建立,此方法仅代表字面含义,也就是连接的对象
    IoSession 被创建完毕的时候,回调这个方法。
    对于UDP 来说,当有数据包收到的时候回调这个方法,因为UDP 是无连接的。
    B. void sessionOpened(IoSession session):
    这个方法在连接被打开时调用,它总是在sessionCreated()方法之后被调用。对于TCP 来
    说,它是在连接被建立之后调用,你可以在这里执行一些认证操作、发送数据等。
    对于UDP 来说,这个方法与sessionCreated()没什么区别,但是紧跟其后执行。如果你每
    隔一段时间,发送一些数据,那么sessionCreated()方法只会在第一次调用,但是
    sessionOpened()方法每次都会调用。
    C. void sessionClosed(IoSession session) :
    对于TCP 来说,连接被关闭时,调用这个方法。
    对于UDP 来说,IoSession 的close()方法被调用时才会毁掉这个方法。
    D. void sessionIdle(IoSession session, IdleStatus status) :
    这个方法在IoSession 的通道进入空闲状态时调用,对于UDP 协议来说,这个方法始终不会
    被调用。
    E. void exceptionCaught(IoSession session, Throwable cause) :
    这个方法在你的程序、Mina 自身出现异常时回调,一般这里是关闭IoSession。
    F. void messageReceived(IoSession session, Object message) :
    接收到消息时调用的方法,也就是用于接收消息的方法,一般情况下,message 是一个
    IoBuffer 类,如果你使用了协议编解码器,那么可以强制转换为你需要的类型。通常我们
    都是会使用协议编解码器的, 就像上面的例子, 因为协议编解码器是
    TextLineCodecFactory,所以我们可以强制转message 为String 类型。
    G. void messageSent(IoSession session, Object message) :
    当发送消息成功时调用这个方法,注意这里的措辞,发送成功之后,也就是说发送消息是不
    能用这个方法的。

    (7.)IoBuffer:
    这个接口是对JAVA NIO 的ByteBuffer 的封装,这主要是因为ByteBuffer 只提供了对基本
    数据类型的读写操作,没有提供对字符串等对象类型的读写方法,使用起来更为方便,另外,
    ByteBuffer 是定长的,如果想要可变,将很麻烦。IoBuffer 的可变长度的实现类似于
    StringBuffer。IoBuffer 与ByteBuffer 一样,都是非线程安全的。本节的一些内容如果不
    清楚,可以参考java.nio.ByteBuffer 接口。
    这个接口有如下常用的方法:
    A. static IoBuffer allocate(int capacity,boolean useDirectBuffer):
    这个方法内部通过SimpleBufferAllocator 创建一个实例,第一个参数指定初始化容量,第
    二个参数指定使用直接缓冲区还是JAVA 内存堆的缓存区,默认为false。
    B. void free():
    释放缓冲区,以便被一些IoBufferAllocator 的实现重用,一般没有必要调用这个方法,除
    非你想提升性能(但可能未必效果明显)。
    C. IoBuffer setAutoExpand(boolean autoExpand):
    这个方法设置IoBuffer 为自动扩展容量,也就是前面所说的长度可变,那么可以看出长度
    可变这个特性默认是不开启的。
    D. IoBuffer setAutoShrink(boolean autoShrink):
    这个方法设置IoBuffer 为自动收缩,这样在compact()方法调用之后,可以裁减掉一些没
    有使用的空间。如果这个方法没有被调用或者设置为false,你也可以通过调用shrink()
    方法手动收缩空间。
    E. IoBuffer order(ByteOrder bo):
    这个方法设置是Big Endian 还是Little Endian,JAVA 中默认是Big Endian,C++和其他
    语言一般是Little Endian。
    F. IoBuffer asReadOnlyBuffer():
    这个方法设置IoBuffer 为只读的。
    G. Boolean prefixedDataAvailable(int prefixLength,int maxDataLength):
    这个方法用于数据的最开始的1、2、4 个字节表示的是数据的长度的情况,prefixLentgh
    表示这段数据的前几个字节(只能是1、2、4 的其中一个)的代表的是这段数据的长度,
    maxDataLength 表示最多要读取的字节数。返回结果依赖于等式
    remaining()-prefixLength>=maxDataLength,也就是总的数据-表示长度的字节,剩下的字
    节数要比打算读取的字节数大或者相等。
    H. String getPrefixedString(int prefixLength,CharsetDecoder decoder):
    如果上面的方法返回true,那么这个方法将开始读取表示长度的字节之后的数据,注意要
    保持这两个方法的prefixLength 的值是一样的。
    G、H 两个方法在后面讲到的PrefixedStringDecoder 中的内部实现使用。
    IoBuffer 剩余的方法与ByteBuffer 都是差不多的,额外增加了一些便利的操作方法,例如:
    IoBuffer putString(String value,CharsetEncoder encoder)可以方便的以指定的编码方
    式存储字符串、InputStream asInputStream()方法从IoBuffer 剩余的未读的数据中转为
    输入流等。

    (8.)IoFuture:
    在Mina 的很多操作中,你会看到返回值是XXXFuture,实际上他们都是IoFuture 的子类,
    看到这样的返回值,这个方法就说明是异步执行的,主要的子类有ConnectFuture、
    CloseFuture 、ReadFuture 、WriteFuture 。这个接口的大部分操作都和
    java.util.concurrent.Future 接口是类似的,譬如:await()、awaitUninterruptibly()
    等,一般我们常用awaitUninterruptibly()方法可以等待异步执行的结果返回。
    这个接口有如下常用的方法:
    A. IoFuture addListener(IoFutureListener<?> listener):
    这个方法用于添加一个监听器, 在异步执行的结果返回时监听器中的回调方法
    operationComplete(IoFuture future),也就是说,这是替代awaitUninterruptibly()方
    法另一种等待异步执行结果的方法,它的好处是不会产生阻塞。
    B. IoFuture removeListener(IoFutureListener<?> listener):
    这个方法用于移除指定的监听器。
    C. IoSession getSession():
    这个方法返回当前的IoSession。
    举个例子,我们在客户端调用connect()方法访问Server 端的时候,实际上这就是一个异
    步执行的方法,也就是调用connect()方法之后立即返回,执行下面的代码,而不管是否连
    接成功。那么如果我想在连接成功之后执行一些事情(譬如:获取连接成功后的IoSession
    对象),该怎么办呢?按照上面的说明,你有如下两种办法:
    第一种:
    ConnectFuture future = connector.connect(new InetSocketAddress(
    HOSTNAME, PORT));
    // 等待是否连接成功,相当于是转异步执行为同步执行。
    future.awaitUninterruptibly();
    // 连接成功后获取会话对象。如果没有上面的等待,由于connect()方法是异步的,session
    可能会无法获取。
    session = future.getSession();
    第二种:
    ConnectFuture future = connector.connect(new InetSocketAddress(
    HOSTNAME, PORT));
    future.addListener(new IoFutureListener<ConnectFuture>() {
    @Override
    public void operationComplete(ConnectFuture future) {
    try {
    Thread.sleep(5000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    IoSession session = future.getSession();
    System.out.println("++++++++++++++++++++++++++++");
    }
    });
    System.out.println("*************");
    为了更好的看清楚使用监听器是异步的,而不是像awaitUninterruptibly()那样会阻塞主
    线程的执行,我们在回调方法中暂停5 秒钟,然后输出+++,在最后输出***。我们执行代码
    之后,你会发现首先输出***(这证明了监听器是异步执行的),然后IoSession 对象Created,
    系统暂停5 秒,然后输出+++,最后IoSession 对象Opened,也就是TCP 连接建立。
    展开全文
  • MINA之基于TCP/IP的Time Server

    千次阅读 2013-09-29 00:14:37
    前提: 1、MINA 2.0.7 Core 2、JDK 1.5 或更高版本 3、[SLF4J|http://www.slf4j.org/] 1.3.0 orgreater  1)Log4J 1.2 users: slf4j-api.jar, slf4j-log4j12.jar, and Log4J 1.2.x  2)

           前提:

    1、MINA 2.0.7 Core

    2、JDK 1.5 或更高版本

    3、[SLF4J|http://www.slf4j.org/] 1.3.0 orgreater

                   1)Log4J 1.2 users: slf4j-api.jar, slf4j-log4j12.jar, and Log4J 1.2.x

                   2)Log4J 1.3 users: slf4j-api.jar,slf4j-log4j13.jar, and Log4J 1.3.x

                   3)java.util.logging users: slf4j-api.jar and slf4j-jdk14.jar

                   注意:确保slf4j-*.jar和框架相配合,比如 slf4j-log4j12.jar and log4j-1.3.x.jar 不能同时使用,否则会失灵。

           第一步:搭建项目

    1、建立项目Java Project:MinaTimeServer

    2、解压apache-mina-2.0.7-bin.zip,进入文件夹apache-mina-2.0.7,将dist目录下的mina-core-2.0.7.jar拷贝到项目中,java需要Add to build Path,JavaWeb直接添加到Web-Inf/lib目录下,会自动构建到路径。

    3、从http://www.slf4j.org/download.html下载slf4j-1.7.5.zip,解压,将里面slf4j-log4j12-1.7.5.jar同样方式添加到项目中。

    4、从http://www.apache.org/dyn/closer.cgi/logging/log4j/1.2.17/log4j-1.2.17.zip 下载log4j-1.2.17.zip,解压,将log4j-1.2.17.jar同样方式添加到项目中。

    并在项目的src目录下,或者新建conf源文件夹目录,建立log4j.properties(必须叫此名):

              

    log4j.rootLogger=DEBUG,console
    
    log4j.logger.sys=DEGUG,system
    
    log4j.logger.busi=INFO,business
    
     
    
    log4j.appender.system=org.apache.log4j.DailyRollingFileAppender
    
    log4j.appender.system.File=rfm-sys
    
    log4j.appender.system.DatePattern=yyyy-MM-dd'.log'
    
    log4j.appender.system.encoding=GBK
    
    log4j.appender.system.layout=org.apache.log4j.PatternLayout
    
    log4j.appender.system.layout.ConversionPattern=[%5p][%d{yyyy-MM-ddHH:mm:ss.SSS}]-%m%n
    
     
    
    log4j.appender.business=org.apache.log4j.DailyRollingFileAppender
    
    log4j.appender.business.File=rfm-busi
    
    log4j.appender.business.DatePattern=yyyy-MM-dd'.log'
    
    log4j.appender.business.encoding=GBK
    
    log4j.appender.business.layout=org.apache.log4j.PatternLayout
    
    log4j.appender.business.layout.ConversionPattern=[%5p][%d{yyyy-MM-ddHH:mm:ss.SSS}]-%m%n
    
     
    
    log4j.appender.console=org.apache.log4j.ConsoleAppender
    
    log4j.appender.console.encoding=GBK
    
    log4j.appender.console.layout=org.apache.log4j.PatternLayout
    
    log4j.appender.console.layout.ConversionPattern=[%5p][%d{yyyy-MM-ddHH\:mm\:ss.SSS}]-%m%n

           第二步:建立时间服务器

    1、  建立TimeServerHandler.java类:

    package zxn.mina;
    
     
    
    importjava.text.SimpleDateFormat;
    
    import java.util.Date;
    
     
    
    importorg.apache.mina.core.service.IoHandlerAdapter;
    
    importorg.apache.mina.core.session.IdleStatus;
    
    importorg.apache.mina.core.session.IoSession;
    
    /**
    
     * 说明:定义为客户端的连接与请求服务的处理器,处理MINA构建的网络应用程序的主要业务逻辑(因为这里处理所有的客户端请求)。
    
     * 功能:返回当前的准确时间
    
     * @author Administrator
    
     * 注意:该处理器类必须实现IoHandler接口,在这我们实现IoHandlerAdapter,它采用适配器模式,简化了代码书写
    
     * 使用:需要将其配置到NioSocketAcceptor才能发挥作用
    
     */
    
    publicclass TimeServerHandler extends IoHandlerAdapter{
    
     
    
         // 处理器必须覆盖该方法,用于处理处理器处理远程连接时发生的异常;否则,异常不能被正确报出
    
         @Override
    
          publicvoid exceptionCaught( IoSession session,Throwable cause ) throws Exception
    
          {
    
             // 该方法仅仅简单地打印出异常,然后关闭当前和客户端连接的会话,这是大多数程序的标准做法,除非处理器能从异常中恢复
    
              cause.printStackTrace();
    
          }
    
     
    
         // 接收客户端的数据,并做出自己想要实现的处理,当前是返回当前时间
    
         // 第二个参数若在write()方法中没有指定协议编解码器,则默认是是IoBuffer类型,写出的数据类型也必须是IoBuffer类型
    
          @Override
    
          publicvoid messageReceived( IoSession session, Objectmessage ) throws Exception
    
          {
    
              String str = message.toString();
    
              if( str.trim().equalsIgnoreCase("bye") ) {
    
              session.write("bye!");
    
                  session.close(true);
    
                  return;
    
              }
    
             
    
              SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
    
              session.write( "the current time is: "+sdf.format(new Date()) );
    
              System.out.println("");
    
          }
    
          // 一旦会话空闲时间超过了call acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 )定义的时间则会被调用
    
          @Override
    
          publicvoid sessionIdle(IoSession session, IdleStatus status ) throws Exception
    
          {
    
              System.out.println( "会话空闲段 " + session.getIdleCount( status ));
    
          }
    
    }

    2、  建立MinaTimeServer.java类:

    package zxn.mina;
    
    importjava.io.IOException;
    
    import java.net.InetSocketAddress;
    
    importjava.nio.charset.Charset;
    
    importorg.apache.mina.core.service.IoAcceptor;
    
    importorg.apache.mina.core.session.IdleStatus;
    
    importorg.apache.mina.filter.codec.ProtocolCodecFilter;
    
    importorg.apache.mina.filter.codec.textline.TextLineCodecFactory;
    
    importorg.apache.mina.filter.logging.LoggingFilter;
    
    importorg.apache.mina.transport.socket.nio.NioSocketAcceptor;
    
     
    
    /**
    
     * 基于TCP/IP,构建时间服务器
    
     * @author Administrator
    
     *
    
     */
    
    publicclass MinaTimeServer {
    
     
    
      // 定义监听的端口号
    
        privatestaticfinalintPORT = 8088;
    
       
    
      publicstaticvoid main( String[]args ) throws IOException
    
        {
    
         // 定义异步Socket接收器
    
            IoAcceptoracceptor = new NioSocketAcceptor();
    
            // 在过滤连末尾添加日志过滤器,记录新创建的会话,发送接收的消息,以及会话的关闭
    
           acceptor.getFilterChain().addLast( "logger", new LoggingFilter() );
    
            // 在过滤连末尾添加编码解码过滤器,用于将二进制数据或者自定义结构的数据转化为消息对象(解码),反之为编码。
    
           acceptor.getFilterChain().addLast( "codec", newProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" ))));
    
            // 设置处理连接的处理器
    
           acceptor.setHandler(  newTimeServerHandler() );
    
            // 设置底层操作系统为每次传入的数据分配多大的空间
    
           acceptor.getSessionConfig().setReadBufferSize( 2048 );
    
            // 设置何时检查闲置会话,第一个参数表示决定会话为闲置的依据(服务端发送消息,客户端发送消息,两者都算),第二个参数表示在这个时间段内,前面依据之任一必须发生,否则被认为是空闲会话。
    
           acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 );
    
            // 将接收器绑定到指定本地端口
    
           acceptor.bind( new InetSocketAddress(PORT) );
    
        }
    
    }


    3、 项目结构如下:

           第三步:测试

    1、进入cmd控制行,输入telnet127.0.0.1 9123

       

    2、回车

     


    4、 再回车,得到服务器返回的时间服务:



    5、 输入bye,则中断和服务器的连接:


    展开全文
  • Mina的大量连接问题

    千次阅读 2016-02-20 22:32:20
    最近用到了Mina,发现在CentOS6.2 上,当接收到400来自客户端的TCP连接的时候,新的TCP的连接能建立成功 但是新建立的TCP连接收到的数据,不能再抛给应用层,而一直堵在缓冲区,如下 使用命令:netstat -nat |...
  • Apache Mina Server 是一网络通信应用框架,也就是说,它主要是对基于TCP/IP、UDP/IP协议栈的通信框架(当然,也可以提供JAVA 对象的序列化服务、虚拟机管道通信服务等),Mina 可以帮助我们快速开发高性能、高...
  • android 客户端用了mina 来实现的tcp连接,一开始使用的时候没什么问题,直到最近服务器返回的数据量变了,就无法接收到数据了,服务器端用的不是mina,在网上查了挺久,了解到mina服务器应该要将超过2k的数据...
  •      Apache Mina Server 2.0 参考手册 最近使用中apache 的mina进行TCP/UDP接口的对接使用,找到以下学习文档 转:...Apache Mina Server 是一网络通信应用框架...
  • 这篇文章也是通过学习mina框架视频来的,网上也有很类似的代码,这里通过自己敲一遍代码,熟悉mina框架的使用以及安卓编程。mina框架作为一网络异步编程框架,它和netty一样,底层实现了nio。 核心类: ...
  • 刚开始用这玩意的时候,很东西不是很了解,所以走了很弯路,大概记录一下。 推荐大家去看看这篇博客,当初也是因为看了这篇博客,才知道自己理解错误的地方:点击打开链接 1.mina框架的编码解码工厂 mina和...
  • Mina-tcp与NIO通信问题

    2017-03-23 17:22:15
    1.消息解码,编码问题开发中,我Client用的是mina,服务端是'C#' 写的NIO,NIO中更是以byte形式来读与写,但是如果用MINA与NIO进行交互的话,NIO可以解码mina,但是mina却死活接收不到来自NIO的信息。折腾了好久,...
  • 接口是服务端IoAcceptor、客户端IoConnector 的抽象,提供IO 服务和管理IoSession 的功能,它有如下几常用的方法: A. TransportMetadata getTransportMetadata(): 这方法获取传输方式的元数据描述信息...
  • 通过上面的两示例,你应该对Mina 如何编写TCP/IP 协议栈的网络通信有了一些感性的认识。 (1.)IoService: 这接口是服务端IoAcceptor、客户端IoConnector 的抽象,提供IO 服务和管理IoSession的功能,它有如下几...
  • 1、我有很终端设备(非手机)通过TCP连接负载均衡服务器,并被分配到相应的后端服务器(通过端口连接,但这些后端服务器除了运行mina TCP长连接服务也提供http服务),请问这些终端设备是否直接与后端服务器TCP...
  • 一 基于tcp协议实现客户端和服务端进行通信 1.1 说明 话不说,上代码, 注意:使用udp不能使用telnet进行向服务端发送信息 1.2 服务端 1.2.1 服务端 package com.ljf.mina.demo.socket; import ...
  • Netty处理TCP连接的session

    千次阅读 2017-06-08 16:40:23
    Netty处理TCP连接的session 在同步阻塞的网络编程中,代码都是按照TCP操作顺序编写的,即创建连接、次读写、关闭连接,这样很容易判断这一系列操作是否是同一连接。而在事件驱动的异步网络编程框架中,IO操作...
  • 如果只连接一个服务器的话,这里可以不用创建不同的解码工厂,如果需要连接多个tcp服务器的话,则需要创建不同的客户端编码处理类了(客户端编码处理类及管理类的写法可以参考上一篇: 第二篇:mina作为tcp服务器...
  • MinaTCP的主要接口

    2013-05-29 09:31:00
    关于TCP连接的关闭: 无论在客户端还是服务端,IoSession 都用于表示底层的一个TCP 连接,那么你会发现无论 是Server 端还是Client 端的IoSession 调用close()方法之后,TCP 连接虽然显示关闭, 但 主线程仍然在...
  • 下面就把camel部署mina:tcp时候遇到一些问题为大家做答,并贴上代码供大家学习! 很多人在部署好后,从客户端发来消息就会报这样的错误: org.apache.mina.common.BufferDataException dataLength Hexdump camel 我...
  • tcp连接检测及重连

    千次阅读 2017-11-02 17:34:48
    mina
  • Apache Mina的SSL连接API

    千次阅读 2014-03-16 10:23:55
    在网上找了N久也没找到有关Mina建立SSL安全连接的细节部分,连官方网站用户手册都说.......即将到来.......实在是不耐烦了,就自己去看了一下源代码,翻译了一下,翻译的比较渣。。。不过能看懂就行了!希望能够造福...
  • 协议编解码器是在使用Mina 的时候你最需要关注的对象,因为在网络传输的数据都是二进制数据(byte),而你在程序中面向的是JAVA 对象,这就需要你实现在发送数据时将JAVA 对象编码二进制数据,而接收数据时将二进制...
  • Socket长连接是Android开发中很基础的功能,很的App都会用到这功能,实现的方式有很,我今天就只写基于Apache Mina框架的实现方式,至于TCP/IP协议相关的知识就不涉及了,想了解更关于Socket长连接知识的,...
  • Apache MINA连接数性能提高

    千次阅读 2014-11-26 11:04:46
    在使用mina的时候,我使用的xp系统,想测试一下mina到底支持多少长连接.但是奇怪的是每次最多支持到415左右. ...增加windows最大TCP连接随机端口数 系统默认TCP随机端口范围为:1024-5000
  • 接口是服务端 IoAcceptor、 客户端 IoConnector 的抽象, 提供 IO 服务和管理 IoSession的功能,它有如下几常用的方法: (1)void addListener(IoServiceListener listener) 这方法可以为 IoService ...
  • TCP连接的几种方式介绍

    千次阅读 2010-07-07 15:03:49
    现在比较常用的TCP应用连接: 1: 同步短连接 Server/Client 最简单 同一端口:客户端发送 --》服务端接收---》客户端 ---close()  2: 同步长连接 Server/Client 连接不断掉 一般用一while(true)死...
  • 其实在mina的源码中,IoService可以总结成五部分service责任、Processor线程处理、handler处理器、接收器和连接器,分别对应着IoService、IoProcessor、IoHandler、IoAcceptor和IoConnector。在代码的中有如下包跟...
  • apache mina连接

    千次阅读 2013-10-11 10:51:16
    apache mina 是较为流行的基于NIO的TCP/IP网络框架,她拥有高性能,以及高的实用性。  可以用于网页游戏服务器,手机游戏服务器。也可作为推送服务器使用。 版本:2.0.x SocketAcceptor acceptor = new ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,200
精华内容 2,480
关键字:

mina多个tcp连接