`
duzc2
  • 浏览: 60768 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类

JAVA NIO和MINA发送数据过程解析

    博客分类:
  • Java
阅读更多

NIO发送数据过程:
1 将信道写入操作加锁保证其他线程不对信道写入(文档中称“是如果另一个线程已经在此通道上发起了一个写入操作,则在该操作完成前此方法的调用被阻塞。”)
2 如果缓冲区为非直接缓冲区,则复制缓冲区内容到直接缓冲区,防止外界对缓冲区内容修改导致发送数据损坏
    * 复制过程分配的内存将被捆绑在线程上,在线程关闭之前,这部分内存不被回收,等IO操作完成后,可重用这部分内存,减少内存分配过程,其性能消耗更多在复制内容上。
    * 直接缓冲区与非直接缓冲区参见ByteBuffer类文档
3 通过JNI调用本地方法直接将缓冲区地址和长度传递给操作系统,由系统进行异步IO操作

由此可见jvm与操作系统共用直接缓冲区。

MINA发送数据过程:
 MINA发送数据过程在
    org.apache.mina.core.polling.AbstractPollingIoProcessor.flushNow(T, long)
    org.apache.mina.core.polling.AbstractPollingIoProcessor.writeBuffer(T, WriteRequest, boolean, int, long)
    org.apache.mina.transport.socket.nio.NioProcessor.write(NioSession, IoBuffer, int)
 方法中。
 
    flashNow方法负责清空IoSession.writeRequestQueue列队。为保证传输效率,flashNow方法尽量将输出长度匹配到接收缓冲区长度的1.5倍。
    flashNow方法循环调用writeBuffer,直到所调用writeBuffer方法返回值总和大于等于接收缓冲区容量的1.5倍、writeBuffer返回0或全部消息发送成功。
    writeBuffer方法负责发送一条消息数据,write方法返回0,writeBuffer将连续尝试256次。
    如果消息完整发送,将调用IoFilterChain.fireMessageSent(req)方法。如果有数据发送,将返回实际发送数据长度,否则返回0。
        * 如果连接支持碎片拼接(如TCP连接),则writeBuffer方法可以决定输出消息的一部分,保证输出数据长度不超过输入缓冲区的1.5倍。
        * 如果连接不支持碎片拼接(如UDP连接),则writterBuffer方法必须将消息完整输出。
    write方法调用信道的write方法,将IoBuffer包装的ByteBuffer放入操作系统缓冲区,并返回结果。
   
由此可见,在基本NIO中,如果系统底层缓冲区填满,SocketChannel.write方法将返回0,业务逻辑必须处理此情况,否则将丢失发送数据。
在MINA中,使用消息分批或拆分方式将最大效率利用系统缓冲区,并保证由于系统缓冲区装满而未发送的消息将重新发送。

 

 

 

相关代码:

 

sun.nio.ch.SocketChannelImpl.write(ByteBuffer)关键代码:
        .
        .
        .
        for (;;) {
            n = IOUtil.write(fd, buf, -1, nd, writeLock);
            if ((n == IOStatus.INTERRUPTED) && isOpen())
            continue;
            return IOStatus.normalize(n);
        }
        .
        .
        .
       
sun.nio.ch.IOUtil.write(FileDescriptor, ByteBuffer[], int, int, NativeDispatcher) 关键代码:
        .
        .
        .
       
    IOVecWrapper vec = IOVecWrapper.get(length);
    .
    .
        ByteBuffer shadow = Util.getTemporaryDirectBuffer(rem);
        hadow.put(buf);
        shadow.flip();
        vec.setShadow(iov_len, shadow);
    .
    .
    .
    long bytesWritten = nd.writev(fd, vec.address, iov_len);
   
SocketDispatcher.writev:
    long writev(FileDescriptor fd, long address, int len) throws IOException {
        return writev0(fd, address, len);
    }

 


特殊返回值定义在:
final class IOStatus {
    static final int EOF = -1;            // End of file
    static final int UNAVAILABLE = -2;        // Nothing available (non-blocking)
    static final int INTERRUPTED = -3;        // System call interrupted
    static final int UNSUPPORTED = -4;        // Operation not supported
    static final int THROWN = -5;        // Exception thrown in JNI code
    static final int UNSUPPORTED_CASE = -6; // This case not supported
   
    static int normalize(int n) {
        if (n == UNAVAILABLE)
            return 0;
        return n;
    }
}
windows下JNI调用:
Java_sun_nio_ch_SocketDispatcher_writev0(JNIEnv *env, jclass clazz,
                                         jobject fdo, jlong address, jint len)
{
    /* set up */
    int i = 0;
    DWORD written = 0;
    jint fd = fdval(env, fdo);
    struct iovec *iovp = (struct iovec *)address;
    WSABUF *bufs = malloc(len * sizeof(WSABUF));

    if (bufs == 0) {
        JNU_ThrowOutOfMemoryError(env, 0);
        return IOS_THROWN;
    }

    if ((isNT() == JNI_FALSE) && (len > 16)) {
        len = 16;
    }

    /* copy iovec into WSABUF */
    for(i=0; i<len; i++) {
        bufs[i].buf = (char *)iovp[i].iov_base;
        bufs[i].len = (u_long)iovp[i].iov_len;
    }
   
    /* read into the buffers */
    i = WSASend((SOCKET)fd, /* Socket */
            bufs,           /* pointers to the buffers */
            (DWORD)len,     /* number of buffers to process */
            &written,       /* receives number of bytes written */
            0,              /* no flags */
            0,              /* no overlapped sockets */
            0);             /* no completion routine */

    /* clean up */
    free(bufs);

    if (i != 0) {
        int theErr = (jint)WSAGetLastError();
        if (theErr == WSAEWOULDBLOCK) {
            return IOS_UNAVAILABLE;
        }
        JNU_ThrowIOExceptionWithLastError(env, "Vector write failed");
        return IOS_THROWN;
    }

    return convertLongReturnVal(env, (jlong)written, JNI_FALSE);
}
windows本地接口
  int WSASend (
  SOCKET s,
  LPWSABUF lpBuffers
  DWORD dwBufferCount,
  LPDWORD lpNumberOfBytesSent,
  DWORD dwFlags,
  LPWSAOVERLAPPED lpOverlapped,
  LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
  );
返回值WSAEWOULDBLOCK    Windows NT: Overlapped sockets: There are too many outstanding overlapped I/O requests. Nonoverlapped sockets: The socket is marked as nonblocking and the send operation cannot be completed immediately.

分享到:
评论

相关推荐

    java-mina通信框架详解.docx

    IoFilter接口定义了一组拦截器,用于实现如日志、黑名单过滤和数据编码解码等功能。数据的编码和解码是使用Mina时最核心的部分,因为它涉及到数据在网络中的传输格式。 IoHandler接口是编写业务逻辑的地方,接收和...

    mina的高级使用,mina文件图片传送,mina发送文件,mina报文处理,mina发送xml和json

    在本文中,我们将深入探讨Mina的高级使用,特别是在文件图片传送、文件发送、XML和JSON报文处理方面的实践。 1. **Mina的高级使用** Mina的核心在于其异步事件驱动的模型,这使得它在处理大量并发连接时表现出色。...

    Mina NIO Socket

    《Mina NIO Socket:深度解析与应用》 在Java世界中,网络编程是一个不可或缺的部分,而Mina NIO(Non-blocking I/O)Socket库则是Java开发者实现高性能、高并发网络服务的重要工具。本文将深入探讨Mina NIO Socket...

    NIO_MINA学习例子_源代码

    NIO (Non-blocking Input/Output) 和 MINA (Multipurpose Infrastructure for Network Applications) 是Java中用于高性能网络应用的两个重要框架。NIO是Java标准库的一部分,提供了与传统IO(Blocking I/O)不同的I/...

    给予mina 协议进行大数据传输

    1. **非阻塞I/O**:MINA使用Java NIO(非阻塞I/O)库,这允许在单个线程中处理多个连接,极大地提高了系统资源的利用率和并发性能。 2. **事件驱动**:MINA基于事件驱动的设计,通过监听网络事件(如连接建立、数据...

    一般Socket客户端与Mina NIO Socket客户端对比示例

    `TestConnector.java`和`SocketTest.java`可能包含了此类客户端的示例代码,展示如何创建和管理Socket连接,以及发送和接收数据的基本流程。 相比之下,Mina NIO是一种基于Java NIO API的网络通信框架,它利用了多...

    java mina组合包

    Java Mina是一个高性能、异步事件驱动的网络应用程序框架,主要用于简化开发服务器端和客户端的网络应用。这个“java mina组合包”看起来包含了Mina库的所有必要组件和可能的扩展,为开发者提供了完整的开发环境。 ...

    springboot 整合mina 源码,nio通讯基础教程,mina框架基础教程.rar

    在实际的通信过程中,客户端需要创建一个Socket连接到服务器的8080端口,然后通过SocketChannel发送和接收数据。服务器端接收到连接请求后,会创建一个IoSession,每个IoSession代表一个客户端连接。通过IoSession,...

    java socket nio 研究

    它可能会继承自`java.nio.channels.ChannelHandler`或自定义的处理器接口,处理接收到的数据并发送时间信息回给客户端。 2. `MinaTimeServer.java`:Mina是一个开源的Java网络应用框架,它提供了一套高度可扩展的、...

    从Jetty、Tomcat和Mina中提炼NIO构架网络服务器的经典模式

    Jetty、Tomcat和Mina都是Java领域中著名的Web服务器和应用服务器,它们在NIO架构上有着相似的设计模式。本文将从这三个框架中提炼出NIO构架网络服务器的经典模式,并逐一解析它们的核心机制。 首先,Jetty的NIO实现...

    Apache mina源代码框架解析

    `NioSocketAcceptor`是Mina提供的非阻塞I/O(NIO)实现,它基于Java的`java.nio`包,能够高效地处理大量并发连接。 在`MinaTimeServer`中,`acceptor.getFilterChain()`用于构建过滤器链,这是Mina中的一个重要概念...

    Mina 2.0快速入门与源码解析

    ### Mina 2.0快速入门与源码解析 #### Mina 2.0 快速入门 Mina 2.0 是一个基于Java NIO技术的高效、可伸缩的网络通信框架,广泛应用于服务器端开发。Mina 2.0 的设计目标是为开发者提供一个易于使用的API,使得...

    基于MINA构建简单高性能的NIO应用

    为了解决这一问题,可以采用Java NIO模型,并结合MINA框架来简化开发和提升性能。 MINA(Multipurpose Infrastructure for Network Applications)是一个开源的网络应用框架,为开发高性能、高可靠性的网络应用程序...

    mina程序执行过程

    在Mina程序执行过程中,主要涉及以下几个关键步骤和组件: 1. **Acceptor 的建立**: Mina 提供了 `NioSocketAcceptor` 类来监听特定的端口,用于接收客户端的连接请求。`NioSocketAcceptor` 使用 Java NIO (非...

    基于MINA构建简单高性能的NIO应用.pdf

    3. **MINA的时间服务器示例**:如何使用MINA搭建一个基础的时间服务器,包括创建服务端监听器、定义协议解码器和编码器、处理客户端连接请求和发送时间响应等步骤。 4. **多客户端处理**:MINA如何通过Selector和多...

    基于Java的实例源码-高性能Java网络框架 MINA.zip

    1. **异步事件驱动模型**:MINA采用非阻塞I/O(NIO)模型,通过事件处理器(Event Handler)和事件驱动(Event Driven)模式,提高了处理大量并发连接的能力。 2. **统一API**:MINA提供了一个统一的API,无论使用...

    以太帧的解析程序JAVA实现

    这部分数据可能需要进一步解析,比如如果是IP数据,可能需要使用`java.net.InetAddress`和`java.net.SocketAddress`进行处理。 7. 检查FCS:虽然Java标准库没有提供内置的CRC计算功能,但你可以找到第三方库或者...

    mina-2.0.4 source code

    《mina-2.0.4源码解析:深入理解Java NIO通信框架》 Apache MINA(Multipurpose Infrastructure for Network Applications)是一个高度可扩展的、高性能的Java网络应用程序框架,主要用于构建服务器端应用。MINA...

    mina传文件案例,客户端加服务端

    2. 创建ProtocolDecoder与ProtocolEncoder:为了解析接收到的数据并编码要发送的数据,我们需要定义自定义的解码器和编码器。在文件传输中,可能需要处理文件的分块传输,所以解码器和编码器应能识别文件块边界。 3...

    mina文件传输

    Mina(MINA,全称Java Minimal Asynchronous Network Library)是一个用Java开发的网络通信框架,主要用于简化网络应用的开发,尤其是TCP和UDP协议的应用。它提供了高度抽象的API,使得开发者可以更专注于业务逻辑,...

Global site tag (gtag.js) - Google Analytics