之前写了一篇文章:java 网络io编程总结(bio、nio、aio均含完整实例代码),介绍了如何使用java原生io支持进行网络编程,本文介绍一种更为简单的方式,即java nio框架。
netty是业界最流行的nio框架之一,具有良好的健壮性、功能、性能、可定制性和可扩展性。同时,它提供的十分简单的api,大大简化了我们的网络编程。
同java io介绍的文章一样,本文所展示的例子,实现了一个相同的功能。
1、服务端
server:
package com.anxpp.io.calculator.netty;
import io.netty.bootstrap.serverbootstrap;
import io.netty.channel.channelfuture;
import io.netty.channel.channelinitializer;
import io.netty.channel.channeloption;
import io.netty.channel.eventloopgroup;
import io.netty.channel.nio.nioeventloopgroup;
import io.netty.channel.socket.socketchannel;
import io.netty.channel.socket.nio.nioserversocketchannel;
public class server {
private int port;
public server(int port) {
this.port = port;
}
public void run() throws exception {
eventloopgroup bossgroup = new nioeventloopgroup();
eventloopgroup workergroup = new nioeventloopgroup();
try {
serverbootstrap b = new serverbootstrap();
b.group(bossgroup, workergroup)
.channel(nioserversocketchannel.class)
.option(channeloption.so_backlog, 1024)
.childoption(channeloption.so_keepalive, true)
.childhandler(new channelinitializer() {
@override
public void initchannel(socketchannel ch) throws exception {
ch.pipeline().addlast(new serverhandler());
}
});
channelfuture f = b.bind(port).sync();
system.out.println("服务器开启:"+port);
f.channel().closefuture().sync();
} finally {
workergroup.shutdowngracefully();
bossgroup.shutdowngracefully();
}
}
public static void main(string[] args) throws exception {
int port;
if (args.length > 0) {
port = integer.parseint(args[0]);
} else {
port = 9090;
}
new server(port).run();
}
}
serverhandler:
package com.anxpp.io.calculator.netty;
import io.netty.buffer.bytebuf;
import io.netty.buffer.unpooled;
import io.netty.channel.channelhandlercontext;
import io.netty.channel.channelinboundhandleradapter;
import java.io.unsupportedencodingexception;
import com.anxpp.io.utils.calculator;
public class serverhandler extends channelinboundhandleradapter {
@override
public void channelread(channelhandlercontext ctx, object msg) throws unsupportedencodingexception {
bytebuf in = (bytebuf) msg;
byte[] req = new byte[in.readablebytes()];
in.readbytes(req);
string body = new string(req,"utf-8");
system.out.println("收到客户端消息:"+body);
string calrresult = null;
try{
calrresult = calculator.instance.cal(body).tostring();
}catch(exception e){
calrresult = "错误的表达式:" + e.getmessage();
}
ctx.write(unpooled.copiedbuffer(calrresult.getbytes()));
}
@override
public void channelreadcomplete(channelhandlercontext ctx) throws exception {
ctx.flush();
}
/**
* 异常处理
*/
@override
public void exceptioncaught(channelhandlercontext ctx, throwable cause) {
cause.printstacktrace();
ctx.close();
}
}
package com.anxpp.io.calculator.netty;
import io.netty.buffer.bytebuf;
import io.netty.buffer.unpooled;
import io.netty.channel.channelhandlercontext;
import io.netty.channel.channelinboundhandleradapter;
import java.io.unsupportedencodingexception;
import com.anxpp.io.utils.calculator;
public class serverhandler extends channelinboundhandleradapter {
@override
public void channelread(channelhandlercontext ctx, object msg) throws unsupportedencodingexception {
bytebuf in = (bytebuf) msg;
byte[] req = new byte[in.readablebytes()];
in.readbytes(req);
string body = new string(req,"utf-8");
system.out.println("收到客户端消息:"+body);
string calrresult = null;
try{
calrresult = calculator.instance.cal(body).tostring();
}catch(exception e){
calrresult = "错误的表达式:" + e.getmessage();
}
ctx.write(unpooled.copiedbuffer(calrresult.getbytes()));
}
@override
public void channelreadcomplete(channelhandlercontext ctx) throws exception {
ctx.flush();
}
/**
* 异常处理
*/
@override
public void exceptioncaught(channelhandlercontext ctx, throwable cause) {
cause.printstacktrace();
ctx.close();
}
}
2、客户端
client:
package com.anxpp.io.calculator.netty;
import io.netty.bootstrap.bootstrap;
import io.netty.channel.channelfuture;
import io.netty.channel.channelinitializer;
import io.netty.channel.channeloption;
import io.netty.channel.eventloopgroup;
import io.netty.channel.nio.nioeventloopgroup;
import io.netty.channel.socket.socketchannel;
import io.netty.channel.socket.nio.niosocketchannel;
import java.util.scanner;
public class client implements runnable{
static clienthandler client = new clienthandler();
public static void main(string[] args) throws exception {
new thread(new client()).start();
@suppresswarnings("resource")
scanner scanner = new scanner(system.in);
while(client.sendmsg(scanner.nextline()));
}
@override
public void run() {
string host = "127.0.0.1";
int port = 9090;
eventloopgroup workergroup = new nioeventloopgroup();
try {
bootstrap b = new bootstrap();
b.group(workergroup);
b.channel(niosocketchannel.class);
b.option(channeloption.so_keepalive, true);
b.handler(new channelinitializer() {
@override
public void initchannel(socketchannel ch) throws exception {
ch.pipeline().addlast(client);
}
});
channelfuture f = b.connect(host, port).sync();
f.channel().closefuture().sync();
} catch (interruptedexception e) {
e.printstacktrace();
} finally {
workergroup.shutdowngracefully();
}
}
}
clienthandler:
package com.anxpp.io.calculator.netty;
import io.netty.buffer.bytebuf;
import io.netty.buffer.unpooled;
import io.netty.channel.channelhandlercontext;
import io.netty.channel.channelinboundhandleradapter;
import java.io.unsupportedencodingexception;
public class clienthandler extends channelinboundhandleradapter {
channelhandlercontext ctx;
/**
* tcp链路简历成功后调用
*/
@override
public void channelactive(channelhandlercontext ctx) throws exception {
this.ctx = ctx;
}
public boolean sendmsg(string msg){
system.out.println("客户端发送消息:"+msg);
byte[] req = msg.getbytes();
bytebuf m = unpooled.buffer(req.length);
m.writebytes(req);
ctx.writeandflush(m);
return msg.equals("q")?false:true;
}
/**
* 收到服务器消息后调用
* @throws unsupportedencodingexception
*/
@override
public void channelread(channelhandlercontext ctx, object msg) throws unsupportedencodingexception {
bytebuf buf = (bytebuf) msg;
byte[] req = new byte[buf.readablebytes()];
buf.readbytes(req);
string body = new string(req,"utf-8");
system.out.println("服务器消息:"+body);
}
/**
* 发生异常时调用
*/
@override
public void exceptioncaught(channelhandlercontext ctx, throwable cause) {
cause.printstacktrace();
ctx.close();
}
}
3、用于计算的工具类
package com.anxpp.io.utils;
import javax.script.scriptengine;
import javax.script.scriptenginemanager;
import javax.script.scriptexception;
public enum calculator {
instance;
private final static scriptengine jse = new scriptenginemanager().getenginebyname("javascript");
public object cal(string expression) throws scriptexception{
return jse.eval(expression);
}
}
4、测试
分别启动服务端和客户端,然后再客户端控制台输入表达式:
1+5+5+5+5+5
客户端发送消息:1+5+5+5+5+5
服务器消息:26
156158*458918+125615
客户端发送消息:156158*458918+125615
服务器消息:7.1663842659e10
1895612+555+5+5+5+5+5+5+5-5*4/4
客户端发送消息:1895612+555+5+5+5+5+5+5+5-5*4/4
服务器消息:1896197
可以看到服务端返回的结果。
查看服务端控制台:
服务器开启:9090
收到客户端消息:1+5+5+5+5+5
收到客户端消息:156158*458918+125615
收到客户端消息:1895612+555+5+5+5+5+5+5+5-5*4/4
5、更多
相关文章:
后续会继续更新netty相关内容,直到一个简陋的通讯服务器完成。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持萬仟网。
希望与广大网友互动??
点此进行留言吧!