ฉันเขียนบทความก่อนหน้านี้: Java Network IO Summary Summary (Bio, Nio และ AIO ทั้งหมดมีรหัสอินสแตนซ์ที่สมบูรณ์) ซึ่งแนะนำวิธีการใช้การสนับสนุน Java Native IO สำหรับการเขียนโปรแกรมเครือข่าย บทความนี้แนะนำวิธีที่ง่ายกว่าคือกรอบ Java Nio
Netty เป็นหนึ่งในเฟรมเวิร์ก NIO ที่ได้รับความนิยมมากที่สุดในอุตสาหกรรมด้วยความแข็งแกร่งความแข็งแกร่งการใช้งานประสิทธิภาพประสิทธิภาพการปรับแต่งและความสามารถในการปรับขนาด ในขณะเดียวกันก็มี API ที่ง่ายมากซึ่งทำให้การเขียนโปรแกรมเครือข่ายของเราง่ายขึ้นอย่างมาก
เช่นเดียวกับบทความที่แนะนำโดย Java IO ตัวอย่างที่แสดงในบทความนี้ใช้ฟังก์ชั่นเดียวกัน
1. ฝั่งเซิร์ฟเวอร์
เซิร์ฟเวอร์:
แพ็คเกจ com.anxpp.io.calculator.netty; นำเข้า io.netty.bootstrap.serverbootstrap; นำเข้า io.netty.channel.channelfuture; นำเข้า io.netty.channel.channelinitializer; นำเข้า io.netty.channel.channeloption; นำเข้า io.netty.channel.eventloopgroup; นำเข้า io.netty.channel.nio.nioeVentloopGroup; นำเข้า io.netty.channel.socket.socketChannel; นำเข้า io.netty.channel.socket.nio.nioserversocketChannel; เซิร์ฟเวอร์ระดับสาธารณะ {พอร์ต INT ส่วนตัว; เซิร์ฟเวอร์สาธารณะ (พอร์ต int) {this.port = พอร์ต; } public void run () พ่นข้อยกเว้น {eventloopgroup bossgroup = new nioEventLoopGroup (); EventLoopGroup WorkerGroup = ใหม่ nioEventLoopGroup (); ลอง {serverbootstrap b = ใหม่ serverbootstrap (); B.Group (BossGroup, WorkerGroup). Channel (nioserversocketChannel.class) .Option (channeloption.so_backlog, 1024) .childoption (channeloption.so_keepalive, true) .childhandler (ช่องทางใหม่ ch.pipeline (). addLast (ใหม่ ServerHandler ());}}); Channelfuture f = b.bind (พอร์ต) .sync (); System.out.println ("เซิร์ฟเวอร์เปิด:"+พอร์ต); F.Channel (). CloseFuture (). sync (); } ในที่สุด {workerGroup.shutdowngracefully (); bossgroup.shutdowngracefully (); }} โมฆะคงที่สาธารณะหลัก (สตริง [] args) พ่นข้อยกเว้น {int พอร์ต; if (args.length> 0) {port = integer.parseint (args [0]); } else {พอร์ต = 9090; } เซิร์ฟเวอร์ใหม่ (พอร์ต) .run (); -ServerHandler:
แพ็คเกจ com.anxpp.io.calculator.netty; นำเข้า io.netty.buffer.bytebuf; นำเข้า io.netty.buffer.unpooled; นำเข้า io.netty.channel.channelhandlerContext; นำเข้า io.netty.channel.channelinboundhandleradapter; นำเข้า java.io.unsupportencodingexception; นำเข้า com.anxpp.io.utils.calculator; Public Class ServerHandler ขยาย channelInBoundHandlerAdapter {@Override โมฆะสาธารณะช่องสัญญาณการอ่าน (channelHandlerContext CTX วัตถุ msg) พ่น unsupportencodexception {byteBuf ใน = (bytebuf) msg; ไบต์ [] req = ไบต์ใหม่ [in.readableBytes ()]; in.readbytes (req); สตริงตัว = สตริงใหม่ (req, "utf-8"); System.out.println ("ข้อความไคลเอนต์ที่ได้รับ:"+body); สตริง calrresult = null; ลอง {calrresult = calculator.instance.cal (ร่างกาย) .toString (); } catch (exception e) {calrresult = "การแสดงออกข้อผิดพลาด:" + e.getMessage (); } ctx.write (unpooled.copiedbuffer (calrresult.getBytes ())); } @Override โมฆะสาธารณะ ChannelReadcomplete (channelHandlerContext CTX) พ่นข้อยกเว้น {ctx.flush (); } / *** การจัดการข้อยกเว้น* / @Override เป็นโมฆะสาธารณะข้อยกเว้น (channelhandlerContext CTX สาเหตุที่โยนได้) {cause.printStackTrace (); ctx.close (); }} แพ็คเกจ com.anxpp.io.calculator.netty; นำเข้า io.netty.buffer.bytebuf; นำเข้า io.netty.buffer.unpooled; นำเข้า io.netty.channel.channelhandlerContext; นำเข้า io.netty.channel.channelinboundhandleradapter; นำเข้า java.io.unsupportencodingexception; นำเข้า com.anxpp.io.utils.calculator; Public Class ServerHandler ขยาย channelInBoundHandlerAdapter {@Override โมฆะสาธารณะช่องสัญญาณการอ่าน (channelHandlerContext CTX วัตถุ msg) พ่น unsupportencodexception {byteBuf ใน = (bytebuf) msg; ไบต์ [] req = ไบต์ใหม่ [in.readableBytes ()]; in.readbytes (req); สตริงตัว = สตริงใหม่ (req, "utf-8"); System.out.println ("ข้อความไคลเอนต์ที่ได้รับ:"+body); สตริง calrresult = null; ลอง {calrresult = calculator.instance.cal (ร่างกาย) .toString (); } catch (exception e) {calrresult = "การแสดงออกข้อผิดพลาด:" + e.getMessage (); } ctx.write (unpooled.copiedbuffer (calrresult.getBytes ())); } @Override โมฆะสาธารณะ ChannelReadcomplete (channelHandlerContext CTX) พ่นข้อยกเว้น {ctx.flush (); } / *** การจัดการข้อยกเว้น* / @Override เป็นโมฆะสาธารณะข้อยกเว้น (channelhandlerContext CTX สาเหตุที่โยนได้) {cause.printStackTrace (); ctx.close (); - 2. ลูกค้า
ลูกค้า:
แพ็คเกจ com.anxpp.io.calculator.netty; นำเข้า io.netty.bootstrap.bootstrap; นำเข้า io.netty.channel.channelfuture; นำเข้า io.netty.channel.channelinitializer; นำเข้า io.netty.channel.channeloption; นำเข้า io.netty.channel.eventloopgroup; นำเข้า io.netty.channel.nio.nioeVentloopGroup; นำเข้า io.netty.channel.socket.socketChannel; นำเข้า io.netty.channel.socket.nio.niosocketChannel; นำเข้า java.util.scanner; ไคลเอนต์คลาสสาธารณะใช้งาน Runnable {Static ClientHandler Client = ใหม่ ClientHandler (); โมฆะคงที่สาธารณะหลัก (สตริง [] args) พ่นข้อยกเว้น {เธรดใหม่ (ไคลเอนต์ใหม่ ()). เริ่ม (); @suppresswarnings ("ทรัพยากร") เครื่องสแกนเนอร์ = สแกนเนอร์ใหม่ (System.in); ในขณะที่ (client.sendmsg (scanner.nextline ())); } @Override โมฆะสาธารณะเรียกใช้ () {สตริงโฮสต์ = "127.0.0.1"; พอร์ต int = 9090; EventLoopGroup WorkerGroup = ใหม่ nioEventLoopGroup (); ลอง {bootstrap b = bootstrap ใหม่ (); B.Group (WorkerGroup); B.Channel (niosocketChannel.class); b.option (channeloption.so_keepalive, true); b.handler (channelinitializer ใหม่ <Ocketchannel> () {@Override โมฆะสาธารณะ initchannel (Socketchannel ch) โยนข้อยกเว้น {ch.pipeline (). addlast (ไคลเอนต์);}}); ช่องทาง f = b.connect (โฮสต์, พอร์ต) .sync (); F.Channel (). CloseFuture (). sync (); } catch (interruptedException e) {e.printStackTrace (); } ในที่สุด {workerGroup.shutdowngracefully (); -clienthandler:
แพ็คเกจ com.anxpp.io.calculator.netty; นำเข้า io.netty.buffer.bytebuf; นำเข้า io.netty.buffer.unpooled; นำเข้า io.netty.channel.channelhandlerContext; นำเข้า io.netty.channel.channelinboundhandleradapter; นำเข้า java.io.unsupportencodingexception; Public Class ClientHandler ขยาย channelinboundhandleradapter {channelhandlercontext ctx; / *** เรียกหลังจาก Resume ลิงก์ TCP สำเร็จ*/ @Override โมฆะสาธารณะช่องสัญญาณ (channelhandlerContext CTX) โยนข้อยกเว้น {this.ctx = ctx; } บูลีนสาธารณะ sendmsg (สตริงผงชูรส) {system.out.println ("ไคลเอนต์ส่งข้อความ:"+msg); ไบต์ [] req = msg.getBytes (); bytebuf m = unpooled.buffer (req.length); M.WriteBytes (REQ); ctx.writeandflush (m); return msg.equals ("q")? เท็จ: จริง; } / *** เรียกหลังจากได้รับข้อความเซิร์ฟเวอร์* @throws unsupportencodingException* / @Override โมฆะสาธารณะช่องสัญญาณการอ่าน (channelHandlerContext CTX, Object MSG) โยน unsupportencodexception {byTebuf buf = (bytebuf) msg; ไบต์ [] req = ไบต์ใหม่ [buf.readablebytes ()]; buf.readbytes (req); สตริงตัว = สตริงใหม่ (req, "utf-8"); System.out.println ("ข้อความเซิร์ฟเวอร์:"+body); } / *** เรียกว่าเมื่อมีข้อยกเว้นเกิดขึ้น* / @Override โมฆะสาธารณะข้อยกเว้น (channelhandlerContext CTX สาเหตุที่โยนได้) {cause.printStackTrace (); ctx.close (); - 3. เครื่องมือสำหรับการคำนวณ
แพ็คเกจ com.anxpp.io.utils; นำเข้า javax.script.scriptEngine; นำเข้า Javax.script.scriptenginginager; นำเข้า Javax.script.scriptException; เครื่องคิดเลข enum สาธารณะ {อินสแตนซ์; สคริปต์คงที่ครั้งสุดท้ายส่วนตัว jse = ใหม่ scriptenginginager (). getEngineByName ("JavaScript"); วัตถุสาธารณะ cal (นิพจน์สตริง) พ่น scriptexception {return jse.eval (นิพจน์); - 4. ทดสอบ
เริ่มต้นเซิร์ฟเวอร์และไคลเอนต์ตามลำดับจากนั้นป้อนนิพจน์บนคอนโซลไคลเอนต์:
1+5+5+5+5+5+5+5+5+5+5+5+5+5+5+5*4/4/4/4/5/5/5/5/5+5+5+5+5+5+5+5+5+5+5+5+5+5+5-5
คุณสามารถดูผลลัพธ์ที่ส่งคืนโดยเซิร์ฟเวอร์
ดูคอนโซลเซิร์ฟเวอร์:
เปิดใช้งานเซิร์ฟเวอร์: 9090 ข้อความไคลเอนต์ที่ได้รับ: 1+5+5+5+5+5 ข้อความไคลเอนต์ที่ได้รับ: 156158*458918+125615 ข้อความไคลเอนต์ที่ได้รับ: 1895612+555+5+5+5+5+5+5+5+5-5-5*4/4/4
5. เพิ่มเติม
บทความที่เกี่ยวข้อง:
สรุปการเขียนโปรแกรม Java Network IO (Bio, NIO, AIO ทั้งหมดมีรหัสอินสแตนซ์ที่สมบูรณ์)
ที่อยู่ซอร์สโค้ด GIT ของตัวอย่างนี้และ Java Bio Nio AIO ตัวอย่าง: https://github.com/anxpp/java-io.git
เนื้อหาที่เกี่ยวข้องกับ Netty จะยังคงได้รับการปรับปรุงต่อไปจนกว่าเซิร์ฟเวอร์การสื่อสารที่เรียบง่ายจะเสร็จสมบูรณ์
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น