netty socket clienterver client 必需配合使用吗

让天下没有难学的技术
Netty框架中的@Skip使用说明
Netty框架中的@Skip使用说明
最近在学习Netty框架,对着教程上写了个简单的netty应用,可是死活调试不成功,对着程序跟教程上看了几遍也找不到原因,后来又重新写了一遍,服务端程序终于调试成功,原因出在了那个@Skip注释上了,代码如下:
package com.chris.
import io.netty.bootstrap.ServerB
import io.netty.buffer.ByteB
import io.netty.buffer.U
import io.netty.channel.ChannelF
import io.netty.channel.ChannelHandler.S
import io.netty.channel.ChannelHandlerA
import io.netty.channel.ChannelHandlerC
import io.netty.channel.ChannelI
import io.netty.channel.ChannelO
import io.netty.channel.ChannelP
import io.netty.channel.EventLoopG
import io.netty.channel.SimpleChannelInboundH
import io.netty.channel.nio.NioEventLoopG
import io.netty.channel.socket.SocketC
import io.netty.channel.socket.nio.NioServerSocketC
import io.netty.example.discard.DiscardServerH
import io.netty.handler.logging.LogL
import io.netty.handler.logging.LoggingH
import io.netty.util.ReferenceCountU
import java.net.SocketA
import java.sql.D
* @author Chris
public class NettyTimerServer {
public void bind(int port) throws Exception{
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workGroup = new NioEventLoopGroup();
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 1024)
.handler(new ))
.childHandler(new ChildChannelHandler());
System.out.println("server bind 8888");
ChannelFuture f = b.bind(port).sync();
System.out.println("finish bind");
f.channel().closeFuture().sync();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
bossGroup.shutdownGracefully();
workGroup.shutdownGracefully();
private class ChildChannelHandler extends ChannelInitializer&SocketChannel&{
/* (non-Javadoc)
* @see io.netty.channel.ChannelInitializer#initChannel(io.netty.channel.Channel)
protected void initChannel(SocketChannel arg0) throws Exception {
System.out.println("server initChannel");
arg0.pipeline().addLast(new TimeServerHandler());
//arg0.pipeline().addl
* @param args
public static void main(String[] args) {
// TODO Auto-generated method stub
new NettyTimerServer().bind(8888);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
class TimeServerHandler extends ChannelHandlerAdapter {
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
public void channelRead(ChannelHandlerContext ctx, Object msg)
throws Exception {
ByteBuf buf = (ByteBuf)
byte[] bytes = new byte[buf.readableBytes()];
buf.readBytes(bytes);
String body = new String(bytes,"UTF-8");
System.out.println("the server receive order:"+body);
String currentTIme = "QUERY CURRENT TIME".equalsIgnoreCase(body)?(new Date(System.currentTimeMillis())).toString():"receive error order";
ByteBuf resp = Unpooled.copiedBuffer(currentTIme.getBytes());
ctx.write(resp);
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress,
SocketAddress localAddress, ChannelPromise promise)
throws Exception {
// TODO Auto-generated method stub
super.connect(ctx, remoteAddress, localAddress, promise);
这个实现类的每个方法上都有一个@Skip注释,去掉注释之后,程序调试成功,使用netty开发的服务端程序可以正常接收和处理客户端连接。
被这个注释坑了一天了,于是特地去看了netty的源码,以下是关于@Skip源码的说明:
* Indicates that the annotated event handler method in {@link ChannelHandler} will not be invoked by
* {@link ChannelPipeline}.
This annotation is only useful when your handler method implementation
* only passes the event through to the next handler, like the following:
* {@code @Skip}
* {@code @Override}
* public void channelActive({@link ChannelHandlerContext} ctx) {
ctx.fireChannelActive(); // do nothing but passing through to the next handler
* {@link #handlerAdded(ChannelHandlerContext)} and {@link #handlerRemoved(ChannelHandlerContext)} are not able to
* pass the event through to the next handler, so they must do nothing when annotated.
* {@code @Skip}
* {@code @Override}
* public void handlerAdded({@link ChannelHandlerContext} ctx) {
// do nothing
* Note that this annotation is not {@linkplain Inherited inherited}.
If you override a method annotated with
* {@link Skip}, it will not be skipped anymore.
Similarly, you can override a method not annotated with
* {@link Skip} and simply pass the event through to the next handler, which reverses the behavior of the
* supertype.
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface Skip {
// no value
大概意思就是说@Skip注释用来在实现了Handler的实现类中的方法上,程序运行过程中如果某个handler实现中的方法被@Skip注释了,则此方法不会被 ChannelPipeline 对象调用,所以,这就是为什么我的服务端程序死活调试不成功的原因。我们可以看看netty内部执行过程中是如何处理@Skip注释的,通过对源码文件全文扫苗,找到了对@Skip注释的处理都集中在了AbstractChannelHandlerContext中,下面贴出处理@Skip相关的方法源码:
* Returns an integer bitset that tells which handler methods were annotated with {@link Skip}.
* It gets the value from {@link #skipFlagsCache} if an handler of the same type were queried before.
* Otherwise, it delegates to {@link #skipFlags0(Class)} to get it.
static int skipFlags(ChannelHandler handler) {
WeakHashMap&Class&?&, Integer& cache = skipFlagsCache.get();
Class&? extends ChannelHandler& handlerType = handler.getClass();
int flagsV
Integer flags = cache.get(handlerType);
if (flags != null) {
flagsVal =
flagsVal = skipFlags0(handlerType);
cache.put(handlerType, Integer.valueOf(flagsVal));
return flagsV
* Determines the {@link #skipFlags} of the specified {@code handlerType} using the reflection API.
static int skipFlags0(Class&? extends ChannelHandler& handlerType) {
int flags = 0;
if (isSkippable(handlerType, "handlerAdded")) {
flags |= MASK_HANDLER_ADDED;
if (isSkippable(handlerType, "handlerRemoved")) {
flags |= MASK_HANDLER_REMOVED;
if (isSkippable(handlerType, "exceptionCaught", Throwable.class)) {
flags |= MASK_EXCEPTION_CAUGHT;
if (isSkippable(handlerType, "channelRegistered")) {
flags |= MASK_CHANNEL_REGISTERED;
if (isSkippable(handlerType, "channelUnregistered")) {
flags |= MASK_CHANNEL_UNREGISTERED;
if (isSkippable(handlerType, "channelActive")) {
flags |= MASK_CHANNEL_ACTIVE;
if (isSkippable(handlerType, "channelInactive")) {
flags |= MASK_CHANNEL_INACTIVE;
if (isSkippable(handlerType, "channelRead", Object.class)) {
flags |= MASK_CHANNEL_READ;
if (isSkippable(handlerType, "channelReadComplete")) {
flags |= MASK_CHANNEL_READ_COMPLETE;
if (isSkippable(handlerType, "channelWritabilityChanged")) {
flags |= MASK_CHANNEL_WRITABILITY_CHANGED;
if (isSkippable(handlerType, "userEventTriggered", Object.class)) {
flags |= MASK_USER_EVENT_TRIGGERED;
if (isSkippable(handlerType, "bind", SocketAddress.class, ChannelPromise.class)) {
flags |= MASK_BIND;
if (isSkippable(handlerType, "connect", SocketAddress.class, SocketAddress.class, ChannelPromise.class)) {
flags |= MASK_CONNECT;
if (isSkippable(handlerType, "disconnect", ChannelPromise.class)) {
flags |= MASK_DISCONNECT;
if (isSkippable(handlerType, "close", ChannelPromise.class)) {
flags |= MASK_CLOSE;
if (isSkippable(handlerType, "deregister", ChannelPromise.class)) {
flags |= MASK_DEREGISTER;
if (isSkippable(handlerType, "read")) {
flags |= MASK_READ;
if (isSkippable(handlerType, "write", Object.class, ChannelPromise.class)) {
flags |= MASK_WRITE;
if (isSkippable(handlerType, "flush")) {
flags |= MASK_FLUSH;
} catch (Exception e) {
// Should never reach here.
PlatformDependent.throwException(e);
@SuppressWarnings("rawtypes")
private static boolean isSkippable(
Class&?& handlerType, String methodName, Class&?&... paramTypes) throws Exception {
Class[] newParamTypes = new Class[paramTypes.length + 1];
newParamTypes[0] = ChannelHandlerContext.
System.arraycopy(paramTypes, 0, newParamTypes, 1, paramTypes.length);
return handlerType.getMethod(methodName, newParamTypes).isAnnotationPresent(Skip.class);
相信不少netty初学者都会碰到此类问题吧,希望这篇文章能对大家有点帮助。
原创文章,转载请注明: 转载自本文链接地址:
Latest posts by huangzixun ()
Related posts:
(5 votes, average: 3.40 out of 5)
Loading...<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
您的访问请求被拒绝 403 Forbidden - ITeye技术社区
您的访问请求被拒绝
亲爱的会员,您的IP地址所在网段被ITeye拒绝服务,这可能是以下两种情况导致:
一、您所在的网段内有网络爬虫大量抓取ITeye网页,为保证其他人流畅的访问ITeye,该网段被ITeye拒绝
二、您通过某个代理服务器访问ITeye网站,该代理服务器被网络爬虫利用,大量抓取ITeye网页
请您点击按钮解除封锁&<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
您的访问请求被拒绝 403 Forbidden - ITeye技术社区
您的访问请求被拒绝
亲爱的会员,您的IP地址所在网段被ITeye拒绝服务,这可能是以下两种情况导致:
一、您所在的网段内有网络爬虫大量抓取ITeye网页,为保证其他人流畅的访问ITeye,该网段被ITeye拒绝
二、您通过某个代理服务器访问ITeye网站,该代理服务器被网络爬虫利用,大量抓取ITeye网页
请您点击按钮解除封锁&

我要回帖

更多关于 android netty client 的文章

 

随机推荐