java非阻塞socket_JAVA基础知识之网络编程——-基于NIO的非阻塞Socket通信

1 packageniochat;2

3 importjava.io.IOException;4 importjava.net.InetSocketAddress;5 importjava.nio.ByteBuffer;6 importjava.nio.channels.Channel;7 importjava.nio.channels.SelectionKey;8 importjava.nio.channels.Selector;9 importjava.nio.channels.ServerSocketChannel;10 importjava.nio.channels.SocketChannel;11 importjava.nio.charset.Charset;12

13 public classNServer {14 //用于检查所有channel状态的selector

15 private Selector selector = null;16 static final int PORT = 3001;17 private Charset charset = Charset.forName("utf-8");18 public void init() throwsIOException, InterruptedException {19 selector =Selector.open();20 //通过open方法打开一个未绑定的ServerSocketChannel实例

21 ServerSocketChannel server =ServerSocketChannel.open();22 InetSocketAddress isa = new InetSocketAddress("127.0.0.1", PORT);23 server.bind(isa);24 //设置非阻塞

25 server.configureBlocking(false);26 //注册ServerSocketChannel到selector

27 server.register(selector, SelectionKey.OP_ACCEPT);28

29 //服务器端需要轮询selector看是否有channel需要通信

30 while ( true) {31 //select()将会一直阻塞,直到选择了至少一个channel(进行通信),此时sector就会调用wakeup(),select()方法才能返回

32 int num =selector.select();33 Thread.sleep(1000);34 //select()方法返回后,用selectedKeys()返回对应channel的SelectionKey集合,通过key.channel()方法可以返回对应的channel实例35 //被选中的key集合selectedKeys表示需要进行IO处理的channel集合,一个key代表一个channel

36 System.out.println("SelectionKey.size = "+selector.selectedKeys().size());37 for(SelectionKey sk : selector.selectedKeys()) {38 //从selector上的已选择的key集合中删除正在处理的key

39 System.out.println("SelectionKey.value = "+sk);40 selector.selectedKeys().remove(sk);41 //如果sk对应channel包含客户端连接请求

42 if(sk.isAcceptable()) {43 //调用accept方法接受请求,产生一个服务器端的SocketChannel44 //在非阻塞模式下,如果没有连接则直接返回null

45 SocketChannel sc =server.accept();46 //设置非阻塞模式

47 sc.configureBlocking(false);48 //将SocketChannel也注册到selector

49 sc.register(selector, SelectionKey.OP_READ);50 //再将sk对应的channel设置为请求准备接受其他请求

51 sk.interestOps(SelectionKey.OP_ACCEPT);52 }53

54 //如果sk对应的channel有数据需要读取

55 if(sk.isReadable()) {56 //获取sk对应的channel

57 SocketChannel sc =(SocketChannel)sk.channel();58 //channel中的数据必须先写入buffer中,然后才能写入进content中

59 ByteBuffer buff = ByteBuffer.allocate(1024);60 String content = "";61 try{62 while(sc.read(buff) > 0) {63 //buffer 复位

64 buff.flip();65 content +=charset.decode(buff);66 }67 System.out.println("读取的数据:"+content);68 //sk复位

69 sk.interestOps(SelectionKey.OP_READ);70 } //遇到channel有异常说明客户端有异常,取消注册此sk

71 catch(IOException ex) {72 //从已选择key集合中取消sk,下一次select()时此channel将自动被删除

73 ex.printStackTrace();74

75 sk.cancel();76 if(sk.channel() != null) {77 sk.channel().close();78 }79

80 }81

82 if (content.length() > 0) {83 //广播

84 for(SelectionKey key : selector.keys()) {85 Channel targetChannel =key.channel();86 if (targetChannel instanceofSocketChannel) {87 SocketChannel dest =(SocketChannel)targetChannel;88 dest.write(charset.encode(content));89 }90 }91 }92 }93

94 }95 }96 }97

98 public static void main(String[] args) throwsIOException, InterruptedException {99 newNServer().init();100 }101 }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值