View Javadoc

    1   /*
    2    *  Licensed to the Apache Software Foundation (ASF) under one
    3    *  or more contributor license agreements.  See the NOTICE file
    4    *  distributed with this work for additional information
    5    *  regarding copyright ownership.  The ASF licenses this file
    6    *  to you under the Apache License, Version 2.0 (the
    7    *  "License"); you may not use this file except in compliance
    8    *  with the License.  You may obtain a copy of the License at
    9    *
    10   *    http://www.apache.org/licenses/LICENSE-2.0
    11   *
    12   *  Unless required by applicable law or agreed to in writing,
    13   *  software distributed under the License is distributed on an
    14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    15   *  KIND, either express or implied.  See the License for the
    16   *  specific language governing permissions and limitations
    17   *  under the License.
    18   *
    19   */
    20  package org.apache.mina.transport.nio;
    21
    22  import java.io.IOException;
    23  import java.net.SocketAddress;
    24  import java.net.SocketException;
    25  import java.nio.channels.DatagramChannel;
    26
    27  import org.apache.mina.api.IdleStatus;
    28  import org.apache.mina.api.IoFuture;
    29  import org.apache.mina.api.IoSession;
    30  import org.apache.mina.api.MinaRuntimeException;
    31  import org.apache.mina.service.executor.IoHandlerExecutor;
    32  import org.apache.mina.service.idlechecker.IndexedIdleChecker;
    33  import org.apache.mina.transport.ConnectFuture;
    34  import org.apache.mina.transport.udp.AbstractUdpClient;
    35  import org.apache.mina.transport.udp.UdpSessionConfig;
    36  import org.apache.mina.util.Assert;
    37
    38  /**
    39   * This class implements a UDP NIO based client.
    40   *
    41   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
    42   */
    43  public class NioUdpClient extends AbstractUdpClient {
    44
    45      /** the SelectorLoop for handling read/write session events */
    46      // This is final, so that we know if it's not initialized
    47      private final SelectorLoopPool readWriteSelectorPool;
    48
    49      private final IndexedIdleChecker idleChecker = new IndexedIdleChecker();
    50
    51      /**
    52       * Create a new instance of NioUdpClient
    53       */
    54      public NioUdpClient() {
    55          this(null);
    56      }
    57
    58      /**
    59       * Create a new instance of NioUdpClient
    60       */
    61      public NioUdpClient(IoHandlerExecutor ioHandlerExecutor) {
    62          super(ioHandlerExecutor);
    63          readWriteSelectorPool = new FixedSelectorLoopPool("Client", 2);
    64          idleChecker.start();
    65      }
    66
    67      /**
    68       * {@inheritDoc}
    69       */
    70      @Override
    71      public IoFuture<IoSession> connect(SocketAddress remoteAddress) {
    72          Assert.assertNotNull(remoteAddress, "remoteAddress");
    73
    74          DatagramChannel ch;
    75          try {
    76              ch = DatagramChannel.open();
    77          } catch (IOException e) {
    78              throw new MinaRuntimeException("can't create a new socket, out of file descriptors ?", e);
    79          }
    80          try {
    81              ch.configureBlocking(false);
    82          } catch (IOException e) {
    83              throw new MinaRuntimeException("can't configure socket as non-blocking", e);
    84          }
    85
    86          UdpSessionConfig config = getSessionConfig();
    87
    88          NioSelectorLoop loop = (NioSelectorLoop) readWriteSelectorPool.getSelectorLoop();
    89
    90          NioUdpSession session = new NioUdpSession(this, idleChecker, ch, null, remoteAddress, loop);
    91
    92          session.setConnected();
    93
    94          // apply idle configuration
    95          session.getConfig().setIdleTimeInMillis(IdleStatus.READ_IDLE, config.getIdleTimeInMillis(IdleStatus.READ_IDLE));
    96          session.getConfig().setIdleTimeInMillis(IdleStatus.WRITE_IDLE,
    97                  config.getIdleTimeInMillis(IdleStatus.WRITE_IDLE));
    98
    99          // Manage the Idle status
    100         idleChecker.sessionRead(session, System.currentTimeMillis());
    101         idleChecker.sessionWritten(session, System.currentTimeMillis());
    102
    103         // apply the default service socket configuration
    104
    105         Boolean reuseAddress = config.isReuseAddress();
    106
    107         if (reuseAddress != null) {
    108             session.getConfig().setReuseAddress(reuseAddress);
    109         }
    110
    111         Integer readBufferSize = config.getReadBufferSize();
    112
    113         if (readBufferSize != null) {
    114             session.getConfig().setReadBufferSize(readBufferSize);
    115         } else {
    116             int rcvBufferSize;
    117             try {
    118                 rcvBufferSize = ch.socket().getReceiveBufferSize();
    119                 session.getConfig().setReadBufferSize(rcvBufferSize);
    120
    121             } catch (SocketException e) {
    122                 throw new MinaRuntimeException("can't configure socket receive buffer size", e);
    123             }
    124         }
    125
    126         Integer sendBufferSize = config.getSendBufferSize();
    127
    128         if (sendBufferSize != null) {
    129             session.getConfig().setSendBufferSize(sendBufferSize);
    130         } else {
    131             int sndBufferSize;
    132             try {
    133                 sndBufferSize = ch.socket().getSendBufferSize();
    134                 session.getConfig().setSendBufferSize(sndBufferSize);
    135             } catch (SocketException e) {
    136                 throw new MinaRuntimeException("can't configure socket send buffe size", e);
    137             }
    138         }
    139
    140         Integer trafficClass = config.getTrafficClass();
    141
    142         if (trafficClass != null) {
    143             session.getConfig().setTrafficClass(trafficClass);
    144         }
    145
    146         loop.register(false, false, true, false, session, ch, null);
    147
    148         ConnectFuture cf = new ConnectFuture();
    149         cf.complete(session);
    150
    151         return cf;
    152     }
    153
    154     /**
    155      * {@inheritDoc}
    156      */
    157     @Override
    158     public IoFuture<IoSession> connect(SocketAddress remoteAddress, SocketAddress localAddress) {
    159         throw new IllegalStateException("not supported for UDP");
    160     }
    161 }