最近使用netty-4.0.23.Final 版本編寫服務端代碼,有個獲取客戶端代碼的小需求,以前使用servlet開發時很機械的就:String?ipAddr="0.0.0.0";
if?(reqest.getHeader("X-Forwarded-For")?==?null)?{
ipAddr?=?reqest.getRemoteAddr();
}else{
ipAddr?=?req.getHeader("X-Forwarded-For");
}
ps:X-Forwarded-For 是使用了代理(如nginx)會附加在HTTP頭域上的。
理解好HTTP協議基礎知識很重要這里不陳述。
Netty提供異步的、事件驅動的網絡應用程序框架和工具,用以快速開發高性能、高可靠性的網絡服務器和客戶端程序,支持多種協議,當然也支持HTTP協議。
啟動Netty服務的程序:public?void?start()?throws?Exception?{
EventLoopGroup?bossGroup?=?new?NioEventLoopGroup(1);
EventLoopGroup?workerGroup?=?new?NioEventLoopGroup();
try?{
ServerBootstrap?bootstrap?=?new?ServerBootstrap();
bootstrap.option(ChannelOption.SO_BACKLOG,?1024);
bootstrap.group(bossGroup,?workerGroup)
.channel(NioServerSocketChannel.class)
.handler(new?LoggingHandler(LogLevel.INFO))
.childHandler(new?ServerHandlerInitializer());
Channel?ch?=?bootstrap.bind(8080).sync().channel();
System.err.println("Open?your?web?browser?and?navigate?to?"
+?("http")?+?"://127.0.0.1:8080/");
ch.closeFuture().sync();
}?catch?(Exception?e)?{
e.printStackTrace();
}?finally?{
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
public?class?ServerHandlerInitializer?extends?ChannelInitializer?{
@Override
protected?void?initChannel(SocketChannel?channel)?throws?Exception?{
ChannelPipeline?p?=?channel.pipeline();
p.addLast(new?HttpRequestDecoder());
p.addLast(new?HttpResponseEncoder());
p.addLast(new?ServerHandler());
}
}
看出NioServerSocketChannel類的源碼可以知道是對java.nio.channels.ServerSocketChannel重新封裝,所以在獲取客戶端IP時調用remoteAddress()強轉成java.net.InetSocketAddress即可獲取。public?class?ServerHandler?extends?SimpleChannelInboundHandler?{
@Override
public?void?channelRead0(ChannelHandlerContext?ctx,?HttpObject?msg)
throws?Exception?{
if?(msg?instanceof?HttpRequest)?{
HttpRequest?mReq?=?(HttpRequest)?msg;
String?clientIP?=?mReq.headers().get("X-Forwarded-For");
if?(clientIP?==?null)?{
InetSocketAddress?insocket?=?(InetSocketAddress)?ctx.channel()
.remoteAddress();
clientIP?=?insocket.getAddress().getHostAddress();
}
}
}
}
這樣我們就可以獲取到客戶端的IP了。