java nio http服务器_使用NIO建立简单的http服务器

1 importjava.io.IOException;2 importjava.net.InetSocketAddress;3 importjava.nio.ByteBuffer;4 importjava.nio.CharBuffer;5 importjava.nio.channels.SelectionKey;6 importjava.nio.channels.Selector;7 importjava.nio.channels.ServerSocketChannel;8 importjava.nio.channels.SocketChannel;9 importjava.nio.charset.Charset;10 importjava.util.Iterator;11

12 public classNioServer {13 privateString ip;14

15 private intport;16

17 privateSelector selector;18

19 public NioServer(String ip, intport) {20 this.ip =ip;21 this.port =port;22 }23

24 public void startListen() throwsIOException {25 selector =Selector.open();26 ServerSocketChannel serverChannel =ServerSocketChannel.open();27 serverChannel.configureBlocking(false);28 serverChannel.register(selector, SelectionKey.OP_ACCEPT);29 serverChannel.bind(newInetSocketAddress(ip, port));30

31 while (true) {32 //不能使用select方法,该方法会阻塞,如果在阻塞过程中channel状态就绪,会因此处阻塞而无法执行。33 //所以,如果调用阻塞方法,下面对channel状态的处理得另起一个常驻线程

34 int result =selector.selectNow();35 if (result == 0) {36 continue;37 }38

39 Iterator it =selector.selectedKeys().iterator();40 while(it.hasNext()) {41 SelectionKey key =it.next();42 if(key.isAcceptable()) {43 accept(key);44 } else if(key.isReadable()) {45 read(key);46 } else if(key.isWritable()) {47 write(key);48 } else{49 System.out.println("Unknow selector type");50 }51

52 //一定要调用remove方法将已经处理过的SelectionKey清除掉,否则会造成后面的请求无法接受

53 it.remove();54 }55 }56 }57

58 private void accept(SelectionKey key) throwsIOException {59 System.out.println("Receive connection");60 ServerSocketChannel serverSocketChannel =(ServerSocketChannel) key.channel();61 SocketChannel channel =serverSocketChannel.accept();62

63 if (channel != null) {64 channel.configureBlocking(false);65 channel.register(selector, SelectionKey.OP_READ);66 }67 System.out.println("Connection end");68 }69

70 private void read(SelectionKey key) throwsIOException {71 System.out.println("Start read");72 SocketChannel channel =(SocketChannel) key.channel();73 ByteBuffer buffer = ByteBuffer.allocate(64);74 boolean hasContent = false;75

76 //这里的判断条件不能是不等于-1,因为channel一直都在,只是在数据被读完后里面为空,返回的长度是0.用-1判断会无限循环无法退出

77 while (channel.read(buffer) > 0) {78 buffer.flip(); //切换为读模式

79 CharBuffer cb = Charset.forName("UTF-8").decode(buffer);80 System.out.print(cb.toString());81 buffer.clear();82 hasContent = true;83 }84

85 if(hasContent) {86 //设置interestOps,用于写响应

87 key.interestOps(SelectionKey.OP_WRITE);88 } else{89 channel.close();90 }91 System.out.println("Read end");92 }93

94 private void write(SelectionKey key) throwsIOException {95 System.out.println("Start write");96 SocketChannel channel =(SocketChannel) key.channel();97

98 String resText =getResponseText();99 ByteBuffer buffer =ByteBuffer.wrap(resText.getBytes());100

101 //此处不可使用channel.write(buffer) != -1来判断,因为在两端都不关闭的情况下,会一直返回0,导致该循环无法退出

102 while(buffer.hasRemaining()) {103 channel.write(buffer);104 }105 channel.close();106 System.out.println("End write");107 }108

109 privateString getResponseText() {110 StringBuffer sb = newStringBuffer();111 sb.append("HTTP/1.1 200 OK\n");112 sb.append("Content-Type: text/html; charset=UTF-8\n");113 sb.append("\n");114 sb.append("");115 sb.append("

");116 sb.append(" ");117 sb.append(" NIO Http Server");118 sb.append(" ");119 sb.append(" ");120 sb.append(" ");121 sb.append("

Hello World!

");122 sb.append(" ");123 sb.append("");124

125 returnsb.toString();126 }127

128 public static voidmain(String[] args) {129 NioServer server = new NioServer("127.0.0.1", 8080);130 try{131 server.startListen();132 } catch(IOException e) {133 e.printStackTrace();134 }135 }136

137 }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值