java NIO服务端和客户端代码实现

  1. package cn.nio; 

  2. import java.io.IOException; 
  3. import java.net.InetSocketAddress; 
  4. import java.nio.ByteBuffer; 
  5. import java.nio.channels.SelectionKey; 
  6. import java.nio.channels.Selector; 
  7. import java.nio.channels.ServerSocketChannel; 
  8. import java.nio.channels.SocketChannel; 
  9. import java.util.Iterator; 

  10. /**
  11. * NIO服务端
  12. * @author 小路
  13. */
  14. public class NIOServer { 
  15. //通道管理器
  16. private Selector selector; 

  17. /**
  18.      * 获得一个ServerSocket通道,并对该通道做一些初始化的工作
  19.      * @param port  绑定的端口号
  20.      * @throws IOException
  21.      */
  22. public void initServer(int port) throws IOException { 
  23. // 获得一个ServerSocket通道
  24.         ServerSocketChannel serverChannel = ServerSocketChannel.open(); 
  25. // 设置通道为非阻塞
  26.         serverChannel.configureBlocking(false); 
  27. // 将该通道对应的ServerSocket绑定到port端口
  28.         serverChannel.socket().bind(new InetSocketAddress(port)); 
  29. // 获得一个通道管理器
  30. this.selector = Selector.open(); 
  31. //将通道管理器和该通道绑定,并为该通道注册SelectionKey.OP_ACCEPT事件,注册该事件后,
  32. //当该事件到达时,selector.select()会返回,如果该事件没到达selector.select()会一直阻塞。
  33.         serverChannel.register(selector, SelectionKey.OP_ACCEPT); 
  34.     } 

  35. /**
  36.      * 采用轮询的方式监听selector上是否有需要处理的事件,如果有,则进行处理
  37.      * @throws IOException
  38.      */
  39. @SuppressWarnings("unchecked") 
  40. public void listen() throws IOException { 
  41.         System.out.println("服务端启动成功!"); 
  42. // 轮询访问selector
  43. while (true) { 
  44. //当注册的事件到达时,方法返回;否则,该方法会一直阻塞
  45.             selector.select(); 
  46. // 获得selector中选中的项的迭代器,选中的项为注册的事件
  47.             Iterator ite = this.selector.selectedKeys().iterator(); 
  48. while (ite.hasNext()) { 
  49.                 SelectionKey key = (SelectionKey) ite.next(); 
  50. // 删除已选的key,以防重复处理
  51.                 ite.remove(); 
  52. // 客户端请求连接事件
  53. if (key.isAcceptable()) { 
  54.                     ServerSocketChannel server = (ServerSocketChannel) key 
  55.                             .channel(); 
  56. // 获得和客户端连接的通道
  57.                     SocketChannel channel = server.accept(); 
  58. // 设置成非阻塞
  59.                     channel.configureBlocking(false); 

  60. //在这里可以给客户端发送信息哦
  61.                     channel.write(ByteBuffer.wrap(new String("向客户端发送了一条信息").getBytes())); 
  62. //在和客户端连接成功之后,为了可以接收到客户端的信息,需要给通道设置读的权限。
  63.                     channel.register(this.selector, SelectionKey.OP_READ); 

  64. // 获得了可读的事件
  65.                 } else if (key.isReadable()) { 
  66.                         read(key); 
  67.                 } 

  68.             } 

  69.         } 
  70.     } 
  71. /**
  72.      * 处理读取客户端发来的信息 的事件
  73.      * @param key
  74.      * @throws IOException
  75.      */
  76. public void read(SelectionKey key) throws IOException{ 
  77. // 服务器可读取消息:得到事件发生的Socket通道
  78.         SocketChannel channel = (SocketChannel) key.channel(); 
  79. // 创建读取的缓冲区
  80.         ByteBuffer buffer = ByteBuffer.allocate(10); 
  81.         channel.read(buffer); 
  82. byte[] data = buffer.array(); 
  83.         String msg = new String(data).trim(); 
  84.         System.out.println("服务端收到信息:"+msg); 
  85.         ByteBuffer outBuffer = ByteBuffer.wrap(msg.getBytes()); 
  86.         channel.write(outBuffer);// 将消息回送给客户端
  87.     } 

  88. /**
  89.      * 启动服务端测试
  90.      * @throws IOException
  91.      */
  92. public static void main(String[] args) throws IOException { 
  93.         NIOServer server = new NIOServer(); 
  94.         server.initServer(8000); 
  95.         server.listen(); 
  96.     } 

客户端:

Java代码 收藏代码

  1. package cn.nio; 

  2. import java.io.IOException; 
  3. import java.net.InetSocketAddress; 
  4. import java.nio.ByteBuffer; 
  5. import java.nio.channels.SelectionKey; 
  6. import java.nio.channels.Selector; 
  7. import java.nio.channels.SocketChannel; 
  8. import java.util.Iterator; 

  9. /**
  10. * NIO客户端
  11. * @author 小路
  12. */
  13. public class NIOClient { 
  14. //通道管理器
  15. private Selector selector; 

  16. /**
  17.      * 获得一个Socket通道,并对该通道做一些初始化的工作
  18.      * @param ip 连接的服务器的ip
  19.      * @param port  连接的服务器的端口号        
  20.      * @throws IOException
  21.      */
  22. public void initClient(String ip,int port) throws IOException { 
  23. // 获得一个Socket通道
  24.         SocketChannel channel = SocketChannel.open(); 
  25. // 设置通道为非阻塞
  26.         channel.configureBlocking(false); 
  27. // 获得一个通道管理器
  28. this.selector = Selector.open(); 

  29. // 客户端连接服务器,其实方法执行并没有实现连接,需要在listen()方法中调
  30. //用channel.finishConnect();才能完成连接
  31.         channel.connect(new InetSocketAddress(ip,port)); 
  32. //将通道管理器和该通道绑定,并为该通道注册SelectionKey.OP_CONNECT事件。
  33.         channel.register(selector, SelectionKey.OP_CONNECT); 
  34.     } 

  35. /**
  36.      * 采用轮询的方式监听selector上是否有需要处理的事件,如果有,则进行处理
  37.      * @throws IOException
  38.      */
  39. @SuppressWarnings("unchecked") 
  40. public void listen() throws IOException { 
  41. // 轮询访问selector
  42. while (true) { 
  43.             selector.select(); 
  44. // 获得selector中选中的项的迭代器
  45.             Iterator ite = this.selector.selectedKeys().iterator(); 
  46. while (ite.hasNext()) { 
  47.                 SelectionKey key = (SelectionKey) ite.next(); 
  48. // 删除已选的key,以防重复处理
  49.                 ite.remove(); 
  50. // 连接事件发生
  51. if (key.isConnectable()) { 
  52.                     SocketChannel channel = (SocketChannel) key 
  53.                             .channel(); 
  54. // 如果正在连接,则完成连接
  55. if(channel.isConnectionPending()){ 
  56.                         channel.finishConnect(); 

  57.                     } 
  58. // 设置成非阻塞
  59.                     channel.configureBlocking(false); 

  60. //在这里可以给服务端发送信息哦
  61.                     channel.write(ByteBuffer.wrap(new String("向服务端发送了一条信息").getBytes())); 
  62. //在和服务端连接成功之后,为了可以接收到服务端的信息,需要给通道设置读的权限。
  63.                     channel.register(this.selector, SelectionKey.OP_READ); 

  64. // 获得了可读的事件
  65.                 } else if (key.isReadable()) { 
  66.                         read(key); 
  67.                 } 

  68.             } 

  69.         } 
  70.     } 
  71. /**
  72.      * 处理读取服务端发来的信息 的事件
  73.      * @param key
  74.      * @throws IOException
  75.      */
  76. public void read(SelectionKey key) throws IOException{ 
  77. //和服务端的read方法一样
  78.     } 


  79. /**
  80.      * 启动客户端测试
  81.      * @throws IOException
  82.      */
  83. public static void main(String[] args) throws IOException { 
  84.         NIOClient client = new NIOClient(); 
  85.         client.initClient("localhost",8000); 
  86.         client.listen(); 
  87.     } 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值