举报投诉联系我们 手机版 热门标签 鳄鱼CMS
您的位置:鳄鱼CMS > java 非阻塞socket Java 非阻塞套接字

java 非阻塞socket Java 非阻塞套接字

2023-03-12 19:31 Java教程

java 非阻塞socket Java 非阻塞套接字

java 非阻塞socket

Java 非阻塞 socket 是一种网络通信技术,它可以让应用程序在不阻塞其他进程的情况下进行数据传输。它是一种异步的方式,可以在不同的进程之间传输数据,而不会影响其他进程的执行。

Java 非阻塞 socket 的工作原理是:当一个 socket 连接请求到达时,它将立即返回一个“已准备就绪”信号,而不是将请求阻塞住,直到有数据可用。当有数据可用时,socket 将通知应用程序并将数据传递出去。

SocketChannel channel = SocketChannel.open();  // 打开 SocketChannel 
channel.configureBlocking(false);  // 设置为非阻塞 
channel.connect(new InetSocketAddress("example.com", 80));  // 连接到 example.com 端口 80 
while (!channel.finishConnect()) {   // 如果还在连接中  
    // 做其他事情  
}  
// 已完成连接  

Java 非阻塞套接字

Java网络教程 - Java非阻塞套接字


使用非阻塞套接字通道,我们必须改变我们对执行顺序的思考方式。

服务器套接字通道

要创建选择器对象,请调用其open()静态方法。

Selector selector = Selector.open();

ServerSocketChannel用于监听来自客户端的新连接请求。

调用其open()静态方法来创建一个ServerSocketChannel。

ServerSocketChannel ssChannel = ServerSocketChannel.open();

默认情况下,服务器套接字通道或套接字通道是阻塞通道。要使其成为非阻塞通道,请调用以下方法。

ssChannel.configureBlocking(false);

选择器

服务器套接字必须向选择器注册才能执行某些操作。

有四种操作,我们可以用选择器注册一个通道。

  • 使用SelectionKey.OP_CONNECT连接操作,可以在客户端为SocketChannel注册。选择器将通知有关连接操作进度。
  • 使用SelectionKey.OP_ACCEPT接受操作,可以在服务器上为ServerSocketChannel注册。当客户端请求新连接到达时,选择器将通知。
  • 使用SelectionKey.OP_READ读取操作,可以在客户端和服务器上为SocketChannel注册。选择器将在通道准备好读取某些数据时通知。
  • 使用SelectionKey.OP_WRITE进行写操作,可以在客户端和服务器上为SocketChannel注册。选择器将在通道准备好写入某些数据时通知。

例子

以下代码显示如何创建非阻塞套接字通道回显服务器程序。

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class Main {
  public static void main(String[] args) throws Exception {
    InetAddress hostIPAddress = InetAddress.getByName("localhost");
    int port = 19000;
    Selector selector = Selector.open();
    ServerSocketChannel ssChannel = ServerSocketChannel.open();
    ssChannel.configureBlocking(false);
    ssChannel.socket().bind(new InetSocketAddress(hostIPAddress, port));
    ssChannel.register(selector, SelectionKey.OP_ACCEPT);
    while (true) {
      if (selector.select() <= 0) {
        continue;
      }
      processReadySet(selector.selectedKeys());
    }
  }
  public static void processReadySet(Set readySet) throws Exception {
    Iterator iterator = readySet.iterator();
    while (iterator.hasNext()) {
      SelectionKey key = (SelectionKey) iterator.next();
      iterator.remove();
      if (key.isAcceptable()) {
        ServerSocketChannel ssChannel = (ServerSocketChannel) key.channel();
        SocketChannel sChannel = (SocketChannel) ssChannel.accept();
        sChannel.configureBlocking(false);
        sChannel.register(key.selector(), SelectionKey.OP_READ);
      }
      if (key.isReadable()) {
        String msg = processRead(key);
        if (msg.length() > 0) {
          SocketChannel sChannel = (SocketChannel) key.channel();
          ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes());
          sChannel.write(buffer);
        }
      }
    }
  }
  public static String processRead(SelectionKey key) throws Exception {
    SocketChannel sChannel = (SocketChannel) key.channel();
    ByteBuffer buffer = ByteBuffer.allocate(1024);
    int bytesCount = sChannel.read(buffer);
    if (bytesCount > 0) {
      buffer.flip();
      return new String(buffer.array());
    }
    return "NoMessage";
  }
}

例2

非阻塞套接字通道回显客户端程序

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.Iterator;
import java.util.Set;

public class Main {
  static BufferedReader userInputReader = null;

  public static boolean processReadySet(Set readySet) throws Exception {
    Iterator iterator = readySet.iterator();
    while (iterator.hasNext()) {
      SelectionKey key = (SelectionKey)
       iterator.next();
      iterator.remove();
      if (key.isConnectable()) {
        boolean connected = processConnect(key);
        if (!connected) {
          return true; // Exit
        }
      }
      if (key.isReadable()) {
        String msg = processRead(key);
        System.out.println("[Server]: " + msg);
      }
      if (key.isWritable()) {
        System.out.print("Please enter a message(Bye to quit):");
        String msg = userInputReader.readLine();
        
        if (msg.equalsIgnoreCase("bye")) {
          return true; // Exit
        }
        SocketChannel sChannel = (SocketChannel) key.channel();
        ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes());
        sChannel.write(buffer);
      }
    }
    return false; // Not done yet
  }
  public static boolean processConnect(SelectionKey key) throws Exception{
    SocketChannel channel = (SocketChannel) key.channel();
    while (channel.isConnectionPending()) {
      channel.finishConnect();
    }
    return true;
  }
  public static String processRead(SelectionKey key) throws Exception {
    SocketChannel sChannel = (SocketChannel) key.channel();
    ByteBuffer buffer = ByteBuffer.allocate(1024);
    sChannel.read(buffer);
    buffer.flip();
    Charset charset = Charset.forName("UTF-8");
    CharsetDecoder decoder = charset.newDecoder();
    CharBuffer charBuffer = decoder.decode(buffer);
    String msg = charBuffer.toString();
    return msg;
  }
  public static void main(String[] args) throws Exception {
    InetAddress serverIPAddress = InetAddress.getByName("localhost");
    int port = 19000;
    InetSocketAddress serverAddress = new InetSocketAddress(
        serverIPAddress, port);
    Selector selector = Selector.open();
    SocketChannel channel = SocketChannel.open();
    channel.configureBlocking(false);
    channel.connect(serverAddress);
    int operations = SelectionKey.OP_CONNECT | SelectionKey.OP_READ
        | SelectionKey.OP_WRITE;
    channel.register(selector, operations);

    userInputReader = new BufferedReader(new InputStreamReader(System.in));
    while (true) {
      if (selector.select() > 0) {
        boolean doneStatus = processReadySet(selector.selectedKeys());
        if (doneStatus) {
          break;
        }
      }
    }
    channel.close();
  }
}
阅读全文
以上是鳄鱼CMS为你收集整理的java 非阻塞socket Java 非阻塞套接字全部内容。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。
相关文章
© 2024 鳄鱼CMS eyucms.com 版权所有 联系我们