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

所属分类: 软件编程 / java 阅读数: 39
收藏 0 赞 0 分享

一、回传协议接口和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 中文参考手册》,也希望大家多多支持脚本之家。

更多精彩内容其他人还在看

Springmvc restful配置遇到的小坑

本文是小编给大家带了的Springmvc restful配置遇到的小小坑,小编给大家带来了问题原因及解决办法,非常不错,具有参考借鉴价值,感兴趣的朋友一起看下吧
收藏 0 赞 0 分享

Java中的匿名内部类小结

java内部类分为: 成员内部类、静态嵌套类、方法内部类、匿名内部类。这篇文章主要介绍了Java中的匿名内部类的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

Java的云打印Lodop

这篇文章主要介绍了Java的云打印Lodop 的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享

Java线程池框架核心代码解析

这篇文章主要针对Java线程池框架核心代码进行详细解析,分析Java线程池框架的实现ThreadPoolExecutor,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

Java 交换两个变量的数值实现方法

下面小编就为大家带来一篇Java 交换两个变量的数值实现方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

全面了解JAVA_BaseDAO数据处理类

下面小编就为大家带来一篇全面了解JAVA_BaseDAO数据处理类。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

java、python、JavaScript以及jquery循环语句的区别

本篇文章主要介绍java、python、JavaScript以及jquery的循环语句的区别,这里整理了它们循环语句语法跟示例,以便大家阅读,更好的区分它们的不同
收藏 0 赞 0 分享

基于JDBC封装的BaseDao(实例代码)

下面小编就为大家带来一篇基于JDBC封装的BaseDao(实例代码)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

简单通用JDBC辅助类封装(实例)

下面小编就为大家带来一篇简单通用JDBC辅助类封装(实例)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

浅谈java线程中生产者与消费者的问题

下面小编就为大家带来一篇浅谈java线程中生产者与消费者的问题。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享
查看更多