content: package com.acgist.snail.net;
  
  import java.io.IOException;
  import java.net.InetSocketAddress;
  import java.net.SocketAddress;
  import java.nio.ByteBuffer;
  import java.nio.channels.DatagramChannel;
  
  import com.acgist.snail.logger.Logger;
  import com.acgist.snail.logger.LoggerFactory;
  
  /**
   * UDP消息代理
   * 
   * @author acgist
   */
  public abstract class UdpMessageHandler extends MessageHandler<DatagramChannel> {
      
      private static final Logger LOGGER = LoggerFactory.getLogger(UdpMessageHandler.class);
  
      /**
       * 远程地址
       * 
       * UdpClient                所有客户端固定地址
       * LSD/Stun/UPNP/Tracker    只要接收的服务端不用管理地址
       * UTP                      主动发送的服务端单独管理消息代理
       * DHT                      被动发送的服务端直接使用消息地址
       */
      protected final InetSocketAddress socketAddress;
      
      /**
       * @param socketAddress 远程地址
       */
      protected UdpMessageHandler(InetSocketAddress socketAddress) {
          this.socketAddress = socketAddress;
      }
      
      @Override
      public void handle(DatagramChannel channel) {
          this.channel = channel;
      }
      
      @Override
      public void send(ByteBuffer buffer, int timeout) throws NetException {
          this.send(buffer, this.remoteSocketAddress());
      }
      
      @Override
      public InetSocketAddress remoteSocketAddress() {
          return this.socketAddress;
      }
  
      @Override
      public void close() {
          LOGGER.debug("UDP连接关闭：{}", this.socketAddress);
          // 标记关闭：不能关闭通道（UDP通道单例复用）
          this.close = true;
      }
      
      /**
       * 发送消息
       * 
       * @param buffer        消息
       * @param socketAddress 地址
       * 
       * @throws NetException 网络异常
       */
      protected final void send(ByteBuffer buffer, SocketAddress socketAddress) throws NetException {
          this.check(buffer);
          try {
              // UDP不用加锁
              final int size = this.channel.send(buffer, socketAddress);
              if(size <= 0) {
                  LOGGER.warn("UDP消息发送失败：{}-{}", socketAddress, size);
              }
          } catch (IOException e) {
              throw new NetException(e);
          }
      }
      
  }
  