一个典型的非阻塞IO程序_Android, Python及开发编程讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  Android, Python及开发编程讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 2172 | 回复: 0   主题: 一个典型的非阻塞IO程序        下一篇 
game
注册用户
等级:新兵
经验:36
发帖:61
精华:0
注册:2011-7-23
状态:离线
发送短消息息给game 加好友    发送短消息息给game 发消息
发表于: IP:您无权察看 2015-12-25 15:46:30 | [全部帖] [楼主帖] 楼主

Java 非阻塞IO常用于高性能的服务器程序。对于阻塞式IO常常需要多个线程来处理客户端的请求,由于线程的开销较大,往往使服务器性能下降很快。而非阻

塞IO只需几个线程就可以胜任大量的请求。对于p2p软件(例如BT软件),也常常使用非阻塞IO,来实现文件交换。

   

下面是一个典型的非阻塞IO程序。客户端向服务器端发起10个连接,服务器端向每个客户端发送”Hello”,并打印出来。


服务器端程序:

 

import java.io.IOException;
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 Server {
             // 服务器端口
    public static int port = 9994;
 
    public Server() {
       init();
    }
 
    public void init() {
       Selector selector = null;
       try {
           //  获得Selector实例
           selector = Selector.open();
           //  获得ServerSocketChannel实例
           ServerSocketChannel serverChannel = ServerSocketChannel.open();
           InetSocketAddress add = new InetSocketAddress("localhost", port);
           //  设为非阻塞模式,默认为阻塞模式
           serverChannel.configureBlocking(false);
           //  channel与一个InetSocketAddress绑定
           serverChannel.socket().bind(add);
           //  向selector注册
           serverChannel.register(selector, SelectionKey.OP_ACCEPT);
       } catch (IOException e) {
           e.printStackTrace();
           return;
       }
       while (true) {
           try {
                      //  如果没有准备好的channel,就在这一直阻塞
              //  注意刚启动时,没有客户端与服务器端连接,会阻塞
              selector.select();
           } catch (IOException e) {
 
              e.printStackTrace();
              break;
           }
           //  返回已经就绪的SelctionKey,然后迭代执行
           Set readyKeys = selector.selectedKeys();
           for (Iterator it = readyKeys.iterator(); it.hasNext();) {
              SelectionKey key = (SelectionKey) it.next();
              //  为防止重复迭代要执行remove,在执行selector.select()时,会自动加入去掉的key
              it.remove();
              try {
                  //  对应于注册的OP_ACCEPT管道,在这里即ServerSocketChannel
                  if (key.isAcceptable()) {
                     ServerSocketChannel server = (ServerSocketChannel) key
                            .channel();
                     // 由于ServerSocketChannel为非阻塞模式,因此不会在这阻塞
                     SocketChannel client = server.accept();
                     client.configureBlocking(false);
                     //  表明接受到一个客户端连接,将其注册到selector
            //  执行selector.select()时可以自动选一个channel
                     client.register(selector, SelectionKey.OP_WRITE);
                     //  对应于注册的OP_WRITE管道,在这里即SocketChannel
                  } else if (key.isWritable()) {
                     SocketChannel client = (SocketChannel) key.channel();
                     // 开辟20个字节的缓冲区
                     ByteBuffer buffer = ByteBuffer.allocate(20);
                     String str = "hello";
                     //  将"hello"封装到buffer
                     buffer = ByteBuffer.wrap(str.getBytes());
                     //  写入客户端
                     client.write(buffer);
                     //  写完hello后取消通道的注册
                     key.cancel();
 
                  }
              } catch (IOException e) {
                  e.printStackTrace();
                  key.cancel();
                  try {
                     //  关闭通道
                     key.channel().close();
                  } catch (IOException e1) {
                     e.printStackTrace();
                  }
              }
           }// end for
       }// end while
 
    }
 
    public static void main(String[] args) {
 
       Server server = new Server();
 
    }
 
}

 

客户端程序:


import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
 
public class Client {
    public Client() {
       init();
    }
 
    public void init() {
        try {
           SocketAddress add = new InetSocketAddress("localhost", Server.port);
           // 返回SocketChannel实例,并绑定SocketAddress
           SocketChannel client = SocketChannel.open(add);
           client.configureBlocking(false);
           ByteBuffer buffer = ByteBuffer.allocate(20);
                                        // 从通道中读取
           client.read(buffer);
                     // 为读取做准备
           buffer.flip();
           String result = "";
           // 每次读一个字符
           while (buffer.hasRemaining())
              result += String.valueOf((char) buffer.get());
           System.out.println(result);
           client.close();
 
       } catch (IOException e) {
 
           e.printStackTrace();
       }
    }
 
    public static void main(String[] args) {
      
       Client client=null;
       for(int i=0;i<10;i++){
          client = new Client();
          System.out.println("client "+i+" has connected");
       }
 
    }
 
}


运行结果:

hello
client 0 has connected
hello
client 1 has connected
hello
client 2 has connected
hello
client 3 has connected
hello
client 4 has connected
hello
client 5 has connected
hello
client 6 has connected
hello
client 7 has connected
hello
client 8 has connected
hello
client 9 has connected













赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论