Netty獲取客戶端IP
阿新 • • 發佈:2019-02-05
最近使用netty-4.0.23.Final 版本編寫服務端程式碼,有個獲取客戶端程式碼的小需求,以前使用servlet開發時很機械的就:
123456 | 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服務的程式:
123456789101112131415161718192021222324252627282930313233 | 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<SocketChannel> { @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即可獲取。
123456789101112131415 | public class ServerHandler extends SimpleChannelInboundHandler<HttpObject> { @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了。