com.mpush.netty.client.NettyClient Maven / Gradle / Ivy
/*
* (C) Copyright 2015-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Contributors:
* [email protected] (夜色)
*/
package com.mpush.netty.client;
import com.mpush.api.service.BaseService;
import com.mpush.api.service.Client;
import com.mpush.api.service.Listener;
import com.mpush.api.service.ServiceException;
import com.mpush.netty.codec.PacketDecoder;
import com.mpush.netty.codec.PacketEncoder;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.InetSocketAddress;
public abstract class NettyClient extends BaseService implements Client {
private static final Logger LOGGER = LoggerFactory.getLogger(NettyClient.class);
private final String host;
private final int port;
private EventLoopGroup workerGroup;
public NettyClient(String host, int port) {
this.host = host;
this.port = port;
}
@Override
public void start(final Listener listener) {
if (started.compareAndSet(false, true)) {
Bootstrap bootstrap = new Bootstrap();
workerGroup = new NioEventLoopGroup();
bootstrap.group(workerGroup)//
.option(ChannelOption.TCP_NODELAY, true)//
.option(ChannelOption.SO_REUSEADDR, true)//
.option(ChannelOption.SO_KEEPALIVE, true)//
.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)//
.channel(NioSocketChannel.class)
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 4000);
bootstrap.handler(new ChannelInitializer() { // (4)
@Override
public void initChannel(SocketChannel ch) throws Exception {
initPipeline(ch.pipeline());
}
});
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
future.addListener((ChannelFutureListener) f -> {
if (f.isSuccess()) {
if (listener != null) listener.onSuccess(port);
LOGGER.info("start netty client success, host={}, port={}", host, port);
} else {
if (listener != null) listener.onFailure(f.cause());
LOGGER.error("start netty client failure, host={}, port={}", host, port, f.cause());
}
});
} else {
listener.onFailure(new ServiceException("client has started!"));
}
}
protected void initPipeline(ChannelPipeline pipeline) {
pipeline.addLast("decoder", getDecoder());
pipeline.addLast("encoder", getEncoder());
pipeline.addLast("handler", getChannelHandler());
}
protected ChannelHandler getDecoder() {
return new PacketDecoder();
}
protected ChannelHandler getEncoder() {
return PacketEncoder.INSTANCE;
}
public abstract ChannelHandler getChannelHandler();
@Override
protected void doStart(Listener listener) throws Throwable {
}
@Override
protected void doStop(Listener listener) throws Throwable {
if (workerGroup != null) {
workerGroup.shutdownGracefully();
}
LOGGER.error("netty client [{}] stopped.", this.getClass().getSimpleName());
}
public String getHost() {
return host;
}
public int getPort() {
return port;
}
@Override
public String toString() {
return "NettyClient{" +
"host='" + host + '\'' +
", port=" + port +
", name=" + this.getClass().getSimpleName() +
'}';
}
}