Java Socket编程实例(五)- NIO UDP实践

 更新时间:2016年06月15日 10:02:02   作者:kingxss  
这篇文章主要讲解Java Socket编程中NIO UDP的实例,希望能给大家做一个参考。

一、回传协议接口和UDP方式实现:

1.接口:

import java.nio.channels.SelectionKey; 
import java.io.IOException; 
 
public interface EchoProtocol { 
 void handleAccept(SelectionKey key) throws IOException; 
 void handleRead(SelectionKey key) throws IOException; 
 void handleWrite(SelectionKey key) throws IOException; 
} 

2.实现:

import java.net.SocketAddress; 
import java.nio.channels.*; 
import java.nio.ByteBuffer; 
import java.io.IOException; 
 
public class UDPEchoSelectorProtocol implements <span style="font-size: 1em; line-height: 1.5;">EchoProtocol </span><span style="font-size: 1em; line-height: 1.5;">{</span> 
  private static final int ECHOMAX = 255; // Maximum size of echo datagram 
 
  static class ClientRecord { 
    public SocketAddress clientAddress; 
    public ByteBuffer buffer = ByteBuffer.allocate(ECHOMAX); 
  } 
 
  public void handleAccept(SelectionKey key) throws IOException { 
     
  } 
 
  public void handleRead(SelectionKey key) throws IOException { 
    DatagramChannel channel = (DatagramChannel) key.channel(); 
    ClientRecord clntRec = (ClientRecord) key.attachment(); 
    clntRec.buffer.clear(); // Prepare buffer for receiving 
    clntRec.clientAddress = channel.receive(clntRec.buffer); 
    if (clntRec.clientAddress != null) { // Did we receive something? 
      // Register write with the selector 
      key.interestOps(SelectionKey.OP_WRITE); 
    } 
  } 
 
  public void handleWrite(SelectionKey key) throws IOException { 
    DatagramChannel channel = (DatagramChannel) key.channel(); 
    ClientRecord clntRec = (ClientRecord) key.attachment(); 
    clntRec.buffer.flip(); // Prepare buffer for sending 
    int bytesSent = channel.send(clntRec.buffer, clntRec.clientAddress); 
    if (bytesSent != 0) { // Buffer completely written? 
      // No longer interested in writes 
      key.interestOps(SelectionKey.OP_READ); 
    } 
  } 
 
}

二、NIO UDP客户端:

import java.net.InetSocketAddress; 
import java.net.SocketException; 
import java.nio.ByteBuffer; 
import java.nio.channels.DatagramChannel; 
 
public class UDPEchoClientNonblocking { 
 
  private static final int TIMEOUT = 3000; // Resend timeout (milliseconds) 
  private static final int MAXTRIES = 255; // Maximum retransmissions 
   
  public static void main(String args[]) throws Exception { 
    // Convert input String to bytes using the default charset 
    byte[] bytesToSend = "0123456789abcdefghijklmnopqrstuvwxyz".getBytes(); 
 
    // Create channel and set to nonblocking 
    DatagramChannel datagramChannel = DatagramChannel.open(); 
    datagramChannel.configureBlocking(false); 
    datagramChannel.socket().setSoTimeout(TIMEOUT); 
     
    ByteBuffer writeBuf = ByteBuffer.wrap(bytesToSend); 
    ByteBuffer readBuf = ByteBuffer.allocate(MAXTRIES); 
     
    datagramChannel = datagramChannel.connect(new InetSocketAddress("127.0.0.1", 5500)); 
 
    int totalBytesRcvd = 0; // Total bytes received so far 
    int bytesRcvd; // Bytes received in last read 
    while (totalBytesRcvd < bytesToSend.length) { 
      if (writeBuf.hasRemaining()) { 
        datagramChannel.write(writeBuf); 
      } 
      if ((bytesRcvd = datagramChannel.read(readBuf)) == -1) { 
        throw new SocketException("Connection closed prematurely"); 
      } 
      totalBytesRcvd += bytesRcvd; 
      System.out.print("."); // Do something else 
    } 
 
    System.out.println("Received: " + new String(readBuf.array(), 0, totalBytesRcvd)); 
    datagramChannel.close(); 
  } 
}

三、NIO UDP服务端:

import java.io.IOException; 
import java.net.InetSocketAddress; 
import java.nio.channels.*; 
import java.util.Iterator; 
 
public class UDPEchoServerSelector { 
 
  private static final int TIMEOUT = 3000; // Wait timeout (milliseconds) 
 
  public static void main(String[] args) throws IOException { 
    // Create a selector to multiplex client connections. 
    Selector selector = Selector.open(); 
 
    DatagramChannel channel = DatagramChannel.open(); 
    channel.configureBlocking(false); 
    channel.socket().bind(new InetSocketAddress(5500)); 
    channel.register(selector, SelectionKey.OP_READ, new UDPEchoSelectorProtocol.ClientRecord()); 
 
    UDPEchoSelectorProtocol echoSelectorProtocol = new UDPEchoSelectorProtocol(); 
    while (true) { // Run forever, receiving and echoing datagrams 
      // Wait for task or until timeout expires 
      if (selector.select(TIMEOUT) == 0) { 
        System.out.print("."); 
        continue; 
      } 
 
      // Get iterator on set of keys with I/O to process 
      Iterator<SelectionKey> keyIter = selector.selectedKeys().iterator(); 
      while (keyIter.hasNext()) { 
        SelectionKey key = keyIter.next(); // Key is bit mask 
 
        // Client socket channel has pending data? 
        if (key.isReadable()) 
          echoSelectorProtocol.handleRead(key); 
 
        // Client socket channel is available for writing and 
        // key is valid (i.e., channel not closed). 
        if (key.isValid() && key.isWritable()) 
          echoSelectorProtocol.handleWrite(key); 
 
        keyIter.remove(); 
      } 
    } 
  } 
 
}

以上就是本文的全部内容,查看更多Java的语法,大家可以关注:《Thinking in Java 中文手册》、《JDK 1.7 参考手册官方英文版》、《JDK 1.6 API java 中文参考手册》、《JDK 1.5 API java 中文参考手册》,也希望大家多多支持脚本之家。

相关文章

  • 手动构建springBoot启动器过程图解

    手动构建springBoot启动器过程图解

    这篇文章主要介绍了手动构建springBoot启动器过程图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04
  • JAVA设计模式中的策略模式你了解吗

    JAVA设计模式中的策略模式你了解吗

    这篇文章主要为大家详细介绍了JAVA设计模式中的策略模式,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03
  • SpringBoot使用Graylog日志收集的实现示例

    SpringBoot使用Graylog日志收集的实现示例

    Graylog是一个生产级别的日志收集系统,集成Mongo和Elasticsearch进行日志收集,这篇文章主要介绍了SpringBoot使用Graylog日志收集的实现示例,感兴趣的小伙伴们可以参考一下
    2019-04-04
  • Spring Security认证器实现过程详解

    Spring Security认证器实现过程详解

    一些权限框架一般都包含认证器和决策器,前者处理登陆验证,后者处理访问资源的控制,这篇文章主要介绍了Spring Security认证器实现过程,需要的朋友可以参考下
    2022-06-06
  • 使用Java实现希尔排序算法的简单示例

    使用Java实现希尔排序算法的简单示例

    这篇文章主要介绍了使用Java实现希尔排序算法的简单示例,希尔排序可以被看作是插入排序的一种更高效的改进版本,需要的朋友可以参考下
    2016-05-05
  • 将SpringBoot的Jar注册成Windows服务的实现方法

    将SpringBoot的Jar注册成Windows服务的实现方法

    当前项目有个地图编辑器,后端用的是SpringBoot框架,外网刚好有一台空闲的Windows服务器就直接拿来用了,将Java程序部署成Windows服务可以用WinSW (Windows Service Wrapper)来实现,文中有详细的操作步骤,需要的朋友可以参考下
    2023-11-11
  • Java 实现完整功能的学生管理系统实例

    Java 实现完整功能的学生管理系统实例

    读万卷书不如行万里路,只学书上的理论是远远不够的,只有在实战中才能获得能力的提升,本篇文章手把手带你用Java实现一个完整版学生管理系统,大家可以在过程中查缺补漏,提升水平
    2021-11-11
  • spring boot+spring cache实现两级缓存(redis+caffeine)

    spring boot+spring cache实现两级缓存(redis+caffeine)

    这篇文章主要介绍了spring boot+spring cache实现两级缓存(redis+caffeine),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-02-02
  • 使用SpringBoot+OkHttp+fastjson实现Github的OAuth第三方登录

    使用SpringBoot+OkHttp+fastjson实现Github的OAuth第三方登录

    这篇文章主要介绍了使用SpringBoot+OkHttp+fastjson实现Github的OAuth第三方登录,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • 通过实例解析Java分布式锁三种实现方法

    通过实例解析Java分布式锁三种实现方法

    这篇文章主要介绍了通过实例解析Java分布式锁三种实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07

最新评论