转载

1、服务端

 

 
  1. package contacts;

  2.  
  3. import java.io.IOException;

  4. import java.net.InetSocketAddress;

  5. import java.net.ServerSocket;

  6. import java.nio.ByteBuffer;

  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.util.Iterator;

  12. import java.util.Set;

  13.  
  14. public class NIOServer {

  15.  
  16. /*标识数字*/

  17. private int flag = 0;

  18. /*缓冲区大小*/

  19. private int BLOCK = 4096;

  20. /*接受数据缓冲区*/

  21. private ByteBuffer sendbuffer = ByteBuffer.allocate(BLOCK);

  22. /*发送数据缓冲区*/

  23. private ByteBuffer receivebuffer = ByteBuffer.allocate(BLOCK);

  24. private Selector selector;

  25.  
  26. public NIOServer(int port) throws IOException {

  27. // 打开服务器套接字通道

  28. ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

  29. // 服务器配置为非阻塞

  30. serverSocketChannel.configureBlocking(false);

  31. // 检索与此通道关联的服务器套接字

  32. ServerSocket serverSocket = serverSocketChannel.socket();

  33. // 进行服务的绑定

  34. serverSocket.bind(new InetSocketAddress(port));

  35. // 通过open()方法找到Selector

  36. selector = Selector.open();

  37. // 注册到selector,等待连接

  38. serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

  39. System.out.println("Server Start----8888:");

  40. }

  41.  
  42.  
  43. // 监听

  44. private void listen() throws IOException {

  45. while (true) {

  46. // 选择一组键,并且相应的通道已经打开

  47. selector.select();

  48. // 返回此选择器的已选择键集。

  49. Set<SelectionKey> selectionKeys = selector.selectedKeys();

  50. Iterator<SelectionKey> iterator = selectionKeys.iterator();

  51. while (iterator.hasNext()) {

  52. SelectionKey selectionKey = iterator.next();

  53. iterator.remove();

  54. handleKey(selectionKey);

  55. }

  56. }

  57. }

  58.  
  59. // 处理请求

  60. private void handleKey(SelectionKey selectionKey) throws IOException {

  61. // 接受请求

  62. ServerSocketChannel server = null;

  63. SocketChannel client = null;

  64. String receiveText;

  65. String sendText;

  66. int count=0;

  67. // 测试此键的通道是否已准备好接受新的套接字连接。

  68. if (selectionKey.isAcceptable()) {

  69. // 返回为之创建此键的通道。

  70. server = (ServerSocketChannel) selectionKey.channel();

  71. // 接受到此通道套接字的连接。

  72. // 此方法返回的套接字通道(如果有)将处于阻塞模式。

  73. client = server.accept();

  74. // 配置为非阻塞

  75. client.configureBlocking(false);

  76. // 注册到selector,等待连接

  77. client.register(selector, SelectionKey.OP_READ);

  78. } else if (selectionKey.isReadable()) {

  79. // 返回为之创建此键的通道。

  80. client = (SocketChannel) selectionKey.channel();

  81. //将缓冲区清空以备下次读取

  82. receivebuffer.clear();

  83. //读取服务器发送来的数据到缓冲区中

  84. count = client.read(receivebuffer);

  85. if (count > 0) {

  86. receiveText = new String( receivebuffer.array(),0,count);

  87. System.out.println("服务器端接受客户端数据--:"+receiveText);

  88. client.register(selector, SelectionKey.OP_WRITE);

  89. }

  90. } else if (selectionKey.isWritable()) {

  91. //将缓冲区清空以备下次写入

  92. sendbuffer.clear();

  93. // 返回为之创建此键的通道。

  94. client = (SocketChannel) selectionKey.channel();

  95. sendText="message from server--" + flag++;

  96. //向缓冲区中输入数据

  97. sendbuffer.put(sendText.getBytes());

  98. //将缓冲区各标志复位,因为向里面put了数据标志被改变要想从中读取数据发向服务器,就要复位

  99. sendbuffer.flip();

  100. //输出到通道

  101. client.write(sendbuffer);

  102. System.out.println("服务器端向客户端发送数据--:"+sendText);

  103. client.register(selector, SelectionKey.OP_READ);

  104. }

  105. }

  106.  
  107. /**

  108. * @param args

  109. * @throws IOException

  110. */

  111. public static void main(String[] args) throws IOException {

  112. // TODO Auto-generated method stub

  113. int port = 8888;

  114. NIOServer server = new NIOServer(port);

  115. server.listen();

  116. }

  117. }

2、客户端

 

 

 
  1. package contacts;

  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.util.Iterator;

  10. import java.util.Set;

  11.  
  12. public class NIOClient {

  13.  
  14. /*标识数字*/

  15. private static int flag = 0;

  16. /*缓冲区大小*/

  17. private static int BLOCK = 4096;

  18. /*接受数据缓冲区*/

  19. private static ByteBuffer sendbuffer = ByteBuffer.allocate(BLOCK);

  20. /*发送数据缓冲区*/

  21. private static ByteBuffer receivebuffer = ByteBuffer.allocate(BLOCK);

  22. /*服务器端地址*/

  23. private final static InetSocketAddress SERVER_ADDRESS = new InetSocketAddress(

  24. "localhost", 8888);

  25.  
  26. public static void main(String[] args) throws IOException {

  27. // TODO Auto-generated method stub

  28. // 打开socket通道

  29. SocketChannel socketChannel = SocketChannel.open();

  30. // 设置为非阻塞方式

  31. socketChannel.configureBlocking(false);

  32. // 打开选择器

  33. Selector selector = Selector.open();

  34. // 注册连接服务端socket动作

  35. socketChannel.register(selector, SelectionKey.OP_CONNECT);

  36. // 连接

  37. socketChannel.connect(SERVER_ADDRESS);

  38. // 分配缓冲区大小内存

  39.  
  40. Set<SelectionKey> selectionKeys;

  41. Iterator<SelectionKey> iterator;

  42. SelectionKey selectionKey;

  43. SocketChannel client;

  44. String receiveText;

  45. String sendText;

  46. int count=0;

  47.  
  48. while (true) {

  49. //选择一组键,其相应的通道已为 I/O 操作准备就绪。

  50. //此方法执行处于阻塞模式的选择操作。

  51. selector.select();

  52. //返回此选择器的已选择键集。

  53. selectionKeys = selector.selectedKeys();

  54. //System.out.println(selectionKeys.size());

  55. iterator = selectionKeys.iterator();

  56. while (iterator.hasNext()) {

  57. selectionKey = iterator.next();

  58. if (selectionKey.isConnectable()) {

  59. System.out.println("client connect");

  60. client = (SocketChannel) selectionKey.channel();

  61. // 判断此通道上是否正在进行连接操作。

  62. // 完成套接字通道的连接过程。

  63. if (client.isConnectionPending()) {

  64. client.finishConnect();

  65. System.out.println("完成连接!");

  66. sendbuffer.clear();

  67. sendbuffer.put("Hello,Server".getBytes());

  68. sendbuffer.flip();

  69. client.write(sendbuffer);

  70. }

  71. client.register(selector, SelectionKey.OP_READ);

  72. } else if (selectionKey.isReadable()) {

  73. client = (SocketChannel) selectionKey.channel();

  74. //将缓冲区清空以备下次读取

  75. receivebuffer.clear();

  76. //读取客户端发送来的数据到缓冲区中

  77. count=client.read(receivebuffer);

  78. if(count>0){

  79. receiveText = new String( receivebuffer.array(),0,count);

  80. System.out.println("客户端接受服务器端数据--:"+receiveText);

  81. client.register(selector, SelectionKey.OP_WRITE);

  82. }

  83.  
  84. } else if (selectionKey.isWritable()) {

  85. sendbuffer.clear();

  86. client = (SocketChannel) selectionKey.channel();

  87. sendText = "message from client--" + (flag++);

  88. sendbuffer.put(sendText.getBytes());

  89. //将缓冲区各标志复位,因为向里面put了数据标志被改变要想从中读取数据发向服务器,就要复位

  90. sendbuffer.flip();

  91. client.write(sendbuffer);

  92. System.out.println("客户端向服务器端发送数据--:"+sendText);

  93. client.register(selector, SelectionKey.OP_READ);

  94. }

  95. }

  96. selectionKeys.clear();

  97. }

  98. }

  99. }

 

3、理解图

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值