zoukankan      html  css  js  c++  java
  • java nio实现非阻塞Socket通信实例

    服务器

    [java] view plain copy
    1. package com.java.xiong.Net17;  
    2.   
    3. import java.io.IOException;  
    4. import java.net.InetSocketAddress;  
    5. import java.nio.ByteBuffer;  
    6. import java.nio.channels.Channel;  
    7. import java.nio.channels.SelectionKey;  
    8. import java.nio.channels.Selector;  
    9. import java.nio.channels.ServerSocketChannel;  
    10. import java.nio.channels.SocketChannel;  
    11. import java.nio.charset.Charset;  
    12.   
    13. public class NServer {  
    14.   
    15.     // 用于检测所有的Channel状态的selector  
    16.     private Selector selector = null;  
    17.     static final int PORT = 30000;  
    18.     // 定义实现编码、解码的字符串集对象  
    19.     private Charset charse = Charset.forName("GBK");  
    20.   
    21.     public void init() throws IOException {  
    22.         selector = Selector.open();  
    23.         // 通过open方法来打开一个未绑定的ServerSocketChannel是咧  
    24.         ServerSocketChannel server = ServerSocketChannel.open();  
    25.         InetSocketAddress isa = new InetSocketAddress("127.0.0.1", PORT);  
    26.         // 将该ServerSocketChannel绑定到指定的IP地址  
    27.         server.bind(isa);  
    28.         // 设置serverSocket已非阻塞方式工作  
    29.         server.configureBlocking(false);  
    30.         // 将server注册到指定的selector对象  
    31.         server.register(selector, SelectionKey.OP_ACCEPT);  
    32.         while (selector.select() > 0) {  
    33.             // 一次处理selector上的每个选择的SelectionKey  
    34.             for (SelectionKey sk : selector.selectedKeys()) {  
    35.                 // 从selector上已选择的Kye集中删除正在处理的SelectionKey  
    36.                 selector.selectedKeys().remove(sk);  
    37.                 // 如果sk对应的Channel包含客户端的连接请求  
    38.                 if (sk.isAcceptable()) {  
    39.                     // 调用accept方法接收连接,产生服务器段的SocketChennal  
    40.                     SocketChannel sc = server.accept();  
    41.                     // 设置采用非阻塞模式  
    42.                     sc.configureBlocking(false);  
    43.                     // 将该SocketChannel注册到selector  
    44.                     sc.register(selector, SelectionKey.OP_READ);  
    45.                 }  
    46.                 // 如果sk对应的Channel有数据需要读取  
    47.                 if (sk.isReadable()) {  
    48.                     // 获取该SelectionKey对银行的Channel,该Channel中有刻度的数据  
    49.                     SocketChannel sc = (SocketChannel) sk.channel();  
    50.                     // 定义备注执行读取数据源的ByteBuffer  
    51.                     ByteBuffer buff = ByteBuffer.allocate(1024);  
    52.                     String content = "";  
    53.                     // 开始读取数据  
    54.                     try {  
    55.                         while (sc.read(buff) > 0) {  
    56.                             buff.flip();  
    57.                             content += charse.decode(buff);  
    58.                         }  
    59.                         System.out.println("读取的数据:" + content);  
    60.                         // 将sk对应的Channel设置成准备下一次读取  
    61.                         sk.interestOps(SelectionKey.OP_READ);  
    62.                     }  
    63.                     // 如果捕获到该sk对银行的Channel出现了异常,表明  
    64.                     // Channel对应的Client出现了问题,所以从Selector中取消  
    65.                     catch (IOException io) {  
    66.                         // 从Selector中删除指定的SelectionKey  
    67.                         sk.cancel();  
    68.                         if (sk.channel() != null) {  
    69.                             sk.channel().close();  
    70.                         }  
    71.                     }  
    72.                     // 如果content的长度大于0,则连天信息不为空  
    73.                     if (content.length() > 0) {  
    74.                         // 遍历selector里注册的所有SelectionKey  
    75.                         for (SelectionKey key : selector.keys()) {  
    76.                             // 获取该key对应的Channel  
    77.                             Channel targerChannel = key.channel();  
    78.                             // 如果该Channel是SocketChannel对象  
    79.                             if (targerChannel instanceof SocketChannel) {  
    80.                                 // 将读取到的内容写入该Channel中  
    81.                                 SocketChannel dest = (SocketChannel) targerChannel;  
    82.                                 dest.write(charse.encode(content));  
    83.                             }  
    84.                         }  
    85.                     }  
    86.                 }  
    87.             }  
    88.         }  
    89.   
    90.     }  
    91.       
    92.     public static void main(String [] args) throws IOException{  
    93.         new NServer().init();  
    94.     }  
    95.   
    96. }  

    客户端

    [java] view plain copy
    1. package com.java.xiong.Net17;  
    2.   
    3. import java.io.IOException;  
    4. import java.net.InetSocketAddress;  
    5. import java.nio.ByteBuffer;  
    6. import java.nio.channels.SelectionKey;  
    7. import java.nio.channels.Selector;  
    8. import java.nio.channels.SocketChannel;  
    9. import java.nio.charset.Charset;  
    10. import java.util.Scanner;  
    11.   
    12. public class NClient {  
    13.       
    14.     //定义检测Sockethannel的Selector对象  
    15.     private Selector  selector=null;  
    16.     static final int PORT=30000;  
    17.     //定义处理编码的字符集  
    18.     private Charset charset=Charset.forName("GBK");  
    19.     //客户端SocketChannel  
    20.     private SocketChannel sc=null;  
    21.       
    22.     public void init() throws IOException{  
    23.         selector=Selector.open();  
    24.         InetSocketAddress isa=new InetSocketAddress("127.0.0.1", PORT);  
    25.         //调用open的静态方法创建连接指定的主机的SocketChannel  
    26.         sc=SocketChannel.open(isa);  
    27.         //设置该sc已非阻塞的方式工作  
    28.         sc.configureBlocking(false);  
    29.         //将SocketChannel对象注册到指定的Selector  
    30.         sc.register(selector, SelectionKey.OP_READ);  
    31.         //启动读取服务器数据端的线程  
    32.         new ClientThread().start();  
    33.         //创建键盘输入流  
    34.         Scanner scan=new Scanner(System.in);  
    35.         while(scan.hasNextLine()){  
    36.             //读取键盘的输入  
    37.             String line=scan.nextLine();  
    38.             //将键盘的内容输出到SocketChanenel中  
    39.             sc.write(charset.encode(line));  
    40.         }  
    41.     }  
    42.       
    43.     //定义读取服务器端的数据的线程  
    44.     private class ClientThread extends Thread{  
    45.   
    46.         @Override  
    47.         public void run() {  
    48.             try{  
    49.                 while(selector.select()>0){  
    50.                     //遍历每个有可能的IO操作的Channel对银行的SelectionKey  
    51.                     for(SelectionKey sk:selector.selectedKeys()){  
    52.                         //删除正在处理的SelectionKey  
    53.                         selector.selectedKeys().remove(sk);  
    54.                         //如果该SelectionKey对应的Channel中有可读的数据  
    55.                         if(sk.isReadable()){  
    56.                             //使用NIO读取Channel中的数据  
    57.                             SocketChannel sc=(SocketChannel)sk.channel();  
    58.                             String content="";  
    59.                             ByteBuffer bff=ByteBuffer.allocate(1024);  
    60.                             while(sc.read(bff)>0){  
    61.                                 sc.read(bff);  
    62.                                 bff.flip();  
    63.                                 content+=charset.decode(bff);  
    64.                             }  
    65.                             //打印读取的内容  
    66.                             System.out.println("聊天信息:"+content);  
    67.                             sk.interestOps(SelectionKey.OP_READ);  
    68.                               
    69.                         }  
    70.                     }  
    71.                 }  
    72.                   
    73.             }catch(IOException io){  
    74.                 io.printStackTrace();  
    75.             }  
    76.         }  
    77.           
    78.     }  
    79.       
    80.     public static void main(String [] args) throws IOException{  
    81.         new NClient().init();  
    82.     }  
    83.   
    84. }  
  • 相关阅读:
    1034: [ZJOI2008]泡泡堂BNB
    1084: [SCOI2005]最大子矩阵
    1046: [HAOI2007]上升序列
    LIS最长上升子序列模板
    1070: [SCOI2007]修车
    1057: [ZJOI2007]棋盘制作
    1066: [SCOI2007]蜥蜴
    1059: [ZJOI2007]矩阵游戏
    1050: [HAOI2006]旅行comf
    1083: [SCOI2005]繁忙的都市
  • 原文地址:https://www.cnblogs.com/wanghuaijun/p/6472458.html
Copyright © 2011-2022 走看看