2021-04-18 11:31  阅读(60)
文章分类:Java 基础教程 文章标签:JavaJava 教程
©  原文作者:w3cschool 原文地址:https://www.w3cschool.cn/java/java-network-tcp-server.html

Java网络教程 - Java异步套接字通道

使用以下两个套接字通道类来执行异步套接字操作:

    java.nio.channels.AsynchronousServerSocketChannel
    java.nio.channels.AsynchronousSocketChannel
    

以下代码显示如何创建使用异步服务器套接字通道的服务器应用程序。

例子

    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.net.SocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.AsynchronousServerSocketChannel;
    import java.nio.channels.AsynchronousSocketChannel;
    import java.nio.channels.CompletionHandler;
    import java.nio.charset.Charset;
    public class Main {
      public static void main(String[] args) throws Exception {
        AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel
            .open();
        String host = "localhost";
        int port = 8989;
        InetSocketAddress sAddr = new InetSocketAddress(host, port);
        server.bind(sAddr);
        System.out.format("Server is listening at %s%n", sAddr);
        Attachment attach = new Attachment();
        attach.server = server;
        server.accept(attach, new ConnectionHandler());
        Thread.currentThread().join();
      }
    }
    class Attachment {
      AsynchronousServerSocketChannel server;
      AsynchronousSocketChannel client;
      ByteBuffer buffer;
      SocketAddress clientAddr;
      boolean isRead;
    }
    
    class ConnectionHandler implements
        CompletionHandler<AsynchronousSocketChannel, Attachment> {
      @Override
      public void completed(AsynchronousSocketChannel client, Attachment attach) {
        try {
          SocketAddress clientAddr = client.getRemoteAddress();
          System.out.format("Accepted a  connection from  %s%n", clientAddr);
          attach.server.accept(attach, this);
          ReadWriteHandler rwHandler = new ReadWriteHandler();
          Attachment newAttach = new Attachment();
          newAttach.server = attach.server;
          newAttach.client = client;
          newAttach.buffer = ByteBuffer.allocate(2048);
          newAttach.isRead = true;
          newAttach.clientAddr = clientAddr;
          client.read(newAttach.buffer, newAttach, rwHandler);
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    
      @Override
      public void failed(Throwable e, Attachment attach) {
        System.out.println("Failed to accept a  connection.");
        e.printStackTrace();
      }
    }
    
    class ReadWriteHandler implements CompletionHandler<Integer, Attachment> {
      @Override
      public void completed(Integer result, Attachment attach) {
        if (result == -1) {
          try {
            attach.client.close();
            System.out.format("Stopped   listening to the   client %s%n",
                attach.clientAddr);
          } catch (IOException ex) {
            ex.printStackTrace();
          }
          return;
        }
    
        if (attach.isRead) {
          attach.buffer.flip();
          int limits = attach.buffer.limit();
          byte bytes[] = new byte[limits];
          attach.buffer.get(bytes, 0, limits);
          Charset cs = Charset.forName("UTF-8");
          String msg = new String(bytes, cs);
          System.out.format("Client at  %s  says: %s%n", attach.clientAddr,
              msg);
          attach.isRead = false; // It is a write
          attach.buffer.rewind();
    
        } else {
          // Write to the client
          attach.client.write(attach.buffer, attach, this);
          attach.isRead = true;
          attach.buffer.clear();
          attach.client.read(attach.buffer, attach, this);
        }
      }
    
      @Override
      public void failed(Throwable e, Attachment attach) {
        e.printStackTrace();
      }
    }
    

上面的代码生成以下结果。

202104181133_1.png

异步客户端套接字通道

AsynchronousSocketChannel类用作客户端应用程序中的异步客户端套接字通道。

以下代码显示如何创建异步客户端套接字通道。

    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.net.InetSocketAddress;
    import java.net.SocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.AsynchronousSocketChannel;
    import java.nio.channels.CompletionHandler;
    import java.nio.charset.Charset;
    import java.util.concurrent.Future;
    
    public class Main {
      public static void main(String[] args) throws Exception {
        AsynchronousSocketChannel channel = AsynchronousSocketChannel.open();
        SocketAddress serverAddr = new InetSocketAddress("localhost", 8989);
        Future<Void> result = channel.connect(serverAddr);
        result.get();
        System.out.println("Connected");
        Attachment attach = new Attachment();
        attach.channel = channel;
        attach.buffer = ByteBuffer.allocate(2048);
        attach.isRead = false;
        attach.mainThread = Thread.currentThread();
    
        Charset cs = Charset.forName("UTF-8");
        String msg = "Hello";
        byte[] data = msg.getBytes(cs);
        attach.buffer.put(data);
        attach.buffer.flip();
    
        ReadWriteHandler readWriteHandler = new ReadWriteHandler();
        channel.write(attach.buffer, attach, readWriteHandler);
        attach.mainThread.join();
      }
    }
    class Attachment {
      AsynchronousSocketChannel channel;
      ByteBuffer buffer;
      Thread mainThread;
      boolean isRead;
    }
    class ReadWriteHandler implements CompletionHandler<Integer, Attachment> {
      @Override
      public void completed(Integer result, Attachment attach) {
        if (attach.isRead) {
          attach.buffer.flip();
          Charset cs = Charset.forName("UTF-8");
          int limits = attach.buffer.limit();
          byte bytes[] = new byte[limits];
          attach.buffer.get(bytes, 0, limits);
          String msg = new String(bytes, cs);
          System.out.format("Server Responded: "+ msg);
          try {
            msg = this.getTextFromUser();
          } catch (Exception e) {
            e.printStackTrace();
          }
          if (msg.equalsIgnoreCase("bye")) {
            attach.mainThread.interrupt();
            return;
          }
          attach.buffer.clear();
          byte[] data = msg.getBytes(cs);
          attach.buffer.put(data);
          attach.buffer.flip();
          attach.isRead = false; // It is a write
          attach.channel.write(attach.buffer, attach, this);
        }else {
          attach.isRead = true;
          attach.buffer.clear();
          attach.channel.read(attach.buffer, attach, this);
        }
      }
      @Override
      public void failed(Throwable e, Attachment attach) {
        e.printStackTrace();
      }
      private String getTextFromUser() throws Exception{
        System.out.print("Please enter a  message  (Bye  to quit):");
        BufferedReader consoleReader = new BufferedReader(
            new InputStreamReader(System.in));
        String msg = consoleReader.readLine();
        return msg;
      }
    }
    
点赞(0)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> Java 异步套接字通道
上一篇
Java 非阻塞套接字
下一篇
Java 数据报套接字通道