⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 selectdemo.java

📁 char22-1 NIO类网络应用 提供了本书第2章的实例NIO类网络应用的源程序;
💻 JAVA
字号:
/*
 * Created on 2005-3-14
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package package1;

import java.io.*;
import java.net.*;
import java.util.*;
import java.nio.*;
import java.nio.channels.*;

public final class SelectDemo {
   //定义服务器类EchoSerer	
   public static class EchoServer {
      private int port;  //服务器使用的端口号
      private ServerSocketChannel channel; 
      private LinkedList clients;
      private Selector readSelector;
      private ByteBuffer buffer;
      public EchoServer(int port) throws IOException
      {
         this.port = port;
         clients = new LinkedList();
         channel = null;
         readSelector = Selector.open();  // 打开一个选择器
         buffer = ByteBuffer.allocate(1024);
      }

	 // 服务器程序在服务循环中调用sericeClients()方法为已接受的客户服务
      public void serviceClients() throws IOException
      {
         Set keys;
         Iterator it;
         SelectionKey key;
         SocketChannel client;
		// 在readSelector上调用select()方法,参数1代表如果调用select的时候
// 那么阻塞最多1秒钟等待可用的客户端连接
         if(readSelector.select(1) > 0) {
            keys = readSelector.selectedKeys(); // 取得代表端通道的键集合
            it = keys.iterator();
		   // 遍历,为每一个客户服务 
            while(it.hasNext()) {
               key = (SelectionKey)it.next();
               if(key.isReadable()) { // 如果通道可读,那么读此通道到buffer中
                  int bytes;
                  client = (SocketChannel)key.channel(); 取得键对应的通道
                  buffer.clear(); // 清空缓冲区中的内容,设置好position,limit,准备接受数据
                  bytes = client.read(buffer); // 从通道中读数据到缓冲中,返回读取得字节数
                  if(bytes >= 0) {
                     buffer.flip(); // 准备将缓冲中的数据写回到通道中
                     client.write(buffer);  // 数据写回到通道中
                  } 
else if(bytes < 0) { // 如果返回小于零的值代表读到了流的末尾
                     clients.remove(client);
				  // 通道关闭时,选择键也被取消
                     client.close();
                  }
               }
            }
         }
      }

	 // 配置和注册代表客户连接的通道对象
      public void registerClient(SocketChannel client) throws IOException
      {
         client.configureBlocking(false);  // 设置此通道使用非阻塞模式	
         client.register(readSelector, SelectionKey.OP_READ); // 将这个通道注册到选择器上
         clients.add(client); //保存这个通道对象
      }

	  //调用这个方法,开始监听并接收客户端请求
      public void listen() throws IOException {
         ServerSocket socket;
         SocketChannel client;
         channel = ServerSocketChannel.open(); // 打开通道
         socket = channel.socket();   //得到与通到相关的socket对象
         socket.bind(new InetSocketAddress(port), 10);   //将scoket榜定在制定的端口上
		//配置通到使用非阻塞模式,在非阻塞模式下,
//可以编写多道程序同时避免使用复杂的多线程
         channel.configureBlocking(false);	
         try {
            while(true) {
// 与通常的程序不同,这里使用channel.accpet()接受客户端连接请求,
// 而不是在socket对象上调用accept()
// 这里在调用accept()方法时如果通道配置为非阻塞模式,,
// 那么accept()方法立即返回null,并不阻塞
               client = channel.accept();	
               if(client != null)
                  registerClient(client); // 注册客户信息
               serviceClients();  // 为以连接的客户服务
            }
         } finally {
            socket.close(); // 关闭socket,关闭socket会同时关闭与此socket关联的通道
         }
      }
   }

   // 主程序类
   public static class Main {
	 //打印使用帮助信息的方法
      public static void usage(String prog) {
         System.err.println("usage: " + prog + " port");
      }
	 //方法run,程序代码的主体
      public void run(String args[])
         throws IllegalArgumentException, NumberFormatException
      {
         EchoServer server;
         if(args.length < 1)
            throw new IllegalArgumentException();
         try {
		   //创建服务器类,将程序的命令行参数中的第一个参数解释为整数,
		   //这个数作为服务器提供服务的端口号
            server = new EchoServer(Integer.parseInt(args[0]));
		   //服务器开始监听端口,提供服务
            server.listen();
         } catch(IOException ioe) {
            ioe.printStackTrace();
            return;
         }
      }
   }

   public static final void main(String args[]) {
      try {
         new Main().run(args);
      } catch(Exception e) {
         Main.usage("SelectDemo");
      }
   }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -