I have the following class. I'm trying to have the WebSocket reconnect in case of failure
public class WebSocketClient extends WebSocketListener {
volatile OkHttpClient client;
volatile WebSocket webSocket;
volatile Boolean isConnected = false;
public WebSocketClient() {
Proxy proxy = null;
if (Main.useProxy) {
tinder.CustomProxy proxyCustom = ProxyManager.GetStaticProxy(ThreadLocalManager.account.get().getProxyId());
proxy = new Proxy(Proxy.Type.HTTP,
new InetSocketAddress(proxyCustom.getProxyIp(), proxyCustom.getProxyPort()));
}
client = new OkHttpClient.Builder().proxy(proxy).readTimeout(2, TimeUnit.SECONDS)
.connectTimeout(2, TimeUnit.SECONDS).build();
Request request = new Request.Builder().url("wss://echo.com/ws")
.addHeader("Accept-Language", "en").build();
webSocket = client.newWebSocket(request, this);
}
#Override
public void onOpen(WebSocket webSocket, Response response) {
AnsiConsole.out.println(Ansi.ansi().fg(Ansi.Color.GREEN).a("Socket connection successful").reset());
isConnected = true;
}
#Override
public void onMessage(WebSocket webSocket, String text) {
System.out.println("Text MESSAGE: " + text);
}
#Override
public void onMessage(WebSocket webSocket, ByteString bytes) {
}
#Override
public void onClosing(WebSocket webSocket, int code, String reason) {
webSocket.close(1000, null);
System.out.println("CLOSE: " + code + " " + reason);
isConnected = false;
}
#Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
isConnected = false;
AnsiConsole.out
.println(Ansi.ansi().fg(Ansi.Color.RED).a("Socket connection failed! will try to reconnect").reset());
while (!isConnected) {
try {
AnsiConsole.out
.println(Ansi.ansi().fg(Ansi.Color.YELLOW).a("Waiting to try socket connection!").reset());
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Request request = new Request.Builder().url("wss://echo.com/ws")
.addHeader("Accept-Language", "en").build();
webSocket = client.newWebSocket(request, this);
}
if (isConnected) {
AnsiConsole.out.println(Ansi.ansi().fg(Ansi.Color.GREEN).a("Socket connection successful").reset());
}
}
public void close() {
if (webSocket != null) {
webSocket.close(1000, "Connection closed");
}
client.dispatcher().executorService().shutdown();
}
}
The problem is if it takes a few attempts to reconnect, then the onFailure method will get called multiple times. Causing multiple web socket connections instead of one.
How can I have the single connection reconnect when the websocket disconnects?
public class WebSocketClient extends WebSocketListener {
volatile OkHttpClient client;
volatile WebSocket webSocket;
volatile Boolean isConnected = false;
public WebSocketClient() {
Proxy proxy = null;
if (Main.useProxy) {
tinder.CustomProxy proxyCustom = ProxyManager.GetStaticProxy(ThreadLocalManager.account.get().getProxyId());
proxy = new Proxy(Proxy.Type.HTTP,
new InetSocketAddress(proxyCustom.getProxyIp(), proxyCustom.getProxyPort()));
}
client = new OkHttpClient.Builder().proxy(proxy).readTimeout(2, TimeUnit.SECONDS)
.connectTimeout(2, TimeUnit.SECONDS).build();
Request request = new Request.Builder().url("wss://echo.com/ws")
.addHeader("Accept-Language", "en").build();
webSocket = client.newWebSocket(request, this);
// First Change
client.connectionPool.evictAll();
}
#Override
public void onOpen(WebSocket webSocket, Response response) {
AnsiConsole.out.println(Ansi.ansi().fg(Ansi.Color.GREEN).a("Socket connection successful").reset());
isConnected = true;
}
#Override
public void onMessage(WebSocket webSocket, String text) {
System.out.println("Text MESSAGE: " + text);
}
#Override
public void onMessage(WebSocket webSocket, ByteString bytes) {
}
#Override
public void onClosing(WebSocket webSocket, int code, String reason) {
webSocket.close(1000, null);
System.out.println("CLOSE: " + code + " " + reason);
isConnected = false;
}
#Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
// Second Change
webSocket.close(1000, null);
close();
Thread.sleep(10000);
Request request = new Request.Builder().url("wss://echo.com/ws")
.addHeader("Accept-Language", "en").build();
webSocket = client.newWebSocket(request, this);
}
public void close() {
if (webSocket != null) {
webSocket.close(1000, "Connection closed");
}
}
}
For multiple idle connection client provide a connectionPool
client.connectionPool().evictAll();
the evictAll() method evicts all the connections.
Related
I have the following java code that I'd like to use in an android app to query an api for continuous lat/lng changes of a device that is running a client app, I want to track the device. I believe the WebSocketCall method I'm attempting to use is deprecated. From what I can tell, there's a problem with how I'm trying to use the webSocket call to create the retrofit client and enqueue the data from the WebSocketListner into retrofit. I've researched several WebSocketListener examples and being a total n00b, I haven't been able to figure out the code. My idea is to keep the connection open to the api via WebSocket and process the data response using retrofit. Any assistance would be greatly appreciated.
private WebSocketCall webSocket;
private void createWebSocket() {
final MainApplication application = (MainApplication) getActivity().getApplication();
application.getServiceAsync(new MainApplication.GetServiceCallback() {
#Override
public void onServiceReady(final OkHttpClient client, final Retrofit retrofit, WebService service) {
User user = application.getUser();
map.moveCamera(CameraUpdateFactory.newLatLngZoom(
new LatLng(user.getLatitude(), user.getLongitude()), user.getZoom()));
service.getDevices().enqueue(new WebServiceCallback<List<Device>>(getContext()) {
#Override
public void onSuccess(retrofit2.Response<List<Device>> response) {
for (Device device : response.body()) {
if (device != null) {
devices.put(device.getId(), device);
}
}
Request request = new Request.Builder().url(retrofit.baseUrl().url().toString() + "api/socket").build();
webSocket = WebSocketCall.create(client, request);
webSocket.enqueue(new WebSocketListener() {
#Override
public void onOpen(WebSocket webSocket, Response response) {
}
#Override
public void onFailure(IOException e, Response response) {
reconnectWebSocket();
}
#Override
public void onMessage(ResponseBody message) throws IOException {
final String data = message.string();
handler.post(new Runnable() {
#Override
public void run() {
try {
handleMessage(data);
} catch (IOException e) {
Log.w(MainFragment.class.getSimpleName(), e);
}
}
});
}
#Override
public void onClose(int code, String reason) {
reconnectWebSocket();
}
});
}
});
}
#Override
public boolean onFailure() {
return false;
}
});
}
So because I'm a total n00b it took some time and a lot of questions to figure this out. Maybe it'll help someone else in the future.
private WebSocket webSocket;
private void createWebSocket() {
final MainApplication application = (MainApplication) getActivity().getApplication();
application.getServiceAsync(new MainApplication.GetServiceCallback() {
#Override
public void onServiceReady(final OkHttpClient client, final Retrofit retrofit, WebService service) {
User user = application.getUser();
map.moveCamera(CameraUpdateFactory.newLatLngZoom(
new LatLng(user.getLatitude(), user.getLongitude()), user.getZoom()));
service.getDevices().enqueue(new WebServiceCallback<List<Device>>(getContext()) {
#Override
public void onSuccess(retrofit2.Response<List<Device>> response) {
for (Device device : response.body()) {
if (device != null) {
devices.put(device.getId(), device);
}
}
Request request = new Request.Builder().url(retrofit.baseUrl().url().toString() + "api/socket").build();
Log.e("WebSockets", "Headers: " + request.headers().toString());
WebSocketListener webSocketListener = new WebSocketListener() {
private static final int NORMAL_CLOSURE_STATUS = 1000;
#Override
public void onOpen(WebSocket webSocket, Response response) {
webSocket.send("{Auth-Token:secret-api-token-here}");
Log.e("WebSockets", "Connection accepted!");
}
#Override
public void onFailure(#NotNull WebSocket webSocket, #NotNull Throwable t, #Nullable Response response) {
reconnectWebSocket();
}
#Override
public void onMessage(#NotNull WebSocket webSocket, #NotNull String text) {
final String data = text;
Log.e("WebSockets", "Receiving : " + text);
handler.post(new Runnable() {
#Override
public void run() {
try {
handleMessage(data);
} catch (IOException e) {
Log.w(MainFragment.class.getSimpleName(), e);
}
}
});
}
#Override
public void onMessage(WebSocket webSocket, ByteString bytes) {
Log.e("WebSockets", "Receiving bytes : " + bytes.hex());
}
#Override
public void onClosing(WebSocket webSocket, int code, String reason) {
webSocket.close(NORMAL_CLOSURE_STATUS, null);
Log.e("WebSockets", "Closing : " + code + " / " + reason);
}
#Override
public void onClosed(#NotNull WebSocket webSocket, int code, #NotNull String reason) {
reconnectWebSocket();
}
};
webSocket = client.newWebSocket(request, webSocketListener);
}
});
}
#Override
public boolean onFailure() {
return false;
}
});
}
I am new in netty I have a tcp client application developed with netty. When i use future get async response from server some response returning but future is not completing into timeout. TCPClient class like following;
public TcpClient {
public boolean connect(Host host) {
try {
Bootstrap clientBootstrap = new Bootstrap()
.group(group)
.channel(NioSocketChannel.class)
.option(ChannelOption.SO_KEEPALIVE,true)
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 50)
.remoteAddress(new InetSocketAddress(host.getIp(), host.getPort()))
.handler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel socketChannel) {
socketChannel.config().setRecvByteBufAllocator(new FixedRecvByteBufAllocator(2146));
FalconClientHandler falconClientHandler = new FalconClientHandler(host);
host.setFalconClientHandler(falconClientHandler);
socketChannel.pipeline().addLast(falconClientHandler);
}
});
channelFuture = clientBootstrap.connect().sync(); //BAŞARI İLE BAĞLANDI
channelFuture.channel().closeFuture().sync();
return host.isActive();
} catch (Exception e) {
log.info("Connection timed out --> " + e);
host.setActive(false);
return false;
} finally {
host.setActive(false);
}
}
public synchronized ResponseFuture send(long transactionId,String message) {
final Map<Long,ResponseFuture> responseFuture = new ConcurrentHashMap<>();
responseFuture.put(transactionId,new ResponseFuture());
if (!hostSelector.getUpHostList().isEmpty()) {
int hostCount = hostSelector.getUpHostList().size();
Host host;
host = hostSelector.getUpHostList().get(index.incrementAndGet() % hostCount);
if (host.isActive()) {
int headerLength = Integer.parseInt(message.substring(8, 12));
log.info("[{}] Host {} Tcp Request",message.substring(52, 52 + headerLength),host.getIp());
channelFuture.addListener((GenericFutureListener<ChannelFuture>) future -> {
log.info("[{}] Tcp request added to map",transactionId);
channelFuture.channel().pipeline().get(FalconClientHandler.class).setResponseFuture(responseFuture);
byte[] byteBuffer = message.getBytes();
channelFuture.channel().writeAndFlush(Unpooled.copiedBuffer(byteBuffer));
});
}
} else {
log.error("AYAKTA HOST YOK");
}
return responseFuture.get(transactionId);
}
}
Send method have transactionId and request message, When i send this message with transaction id response will return with this thransaction id. I am calling this send like following;
ResponseFuture responseFuture = falconClient.send(Long.valueOf(transactionId), finalMessage);
try {
Object obj = responseFuture.get(ddaTimeoutParam, TimeUnit.MILLISECONDS);
if(obj!=null) {
response = obj.toString();
ddaDelta = System.currentTimeMillis()-ddaRequestStartTime;
}
} catch (InterruptedException | ExecutionException | TimeoutException e) {
log.warn("[{}] DDA timeout. Timeout parameter: {}",transactionId,ddaTimeoutParam);
responseFuture.cancel(true);
response = "TIMEOUT";
ddaDelta = System.currentTimeMillis()-ddaRequestStartTime;
}
Response future is a basic Future implementation class. Put and get methods like that;
public class ResponseFuture implements Future<String> {
private volatile State state = State.WAITING;
ArrayBlockingQueue<String> blockingResponse = new ArrayBlockingQueue<String>(1);
private enum State {
WAITING,
DONE
}
#Override
public String get(long timeout, TimeUnit unit) throws InterruptedException,
ExecutionException, TimeoutException {
final String responseAfterWait = blockingResponse.poll(timeout, unit);
if (responseAfterWait == null) {
throw new TimeoutException();
}
return responseAfterWait;
}
public void set(String msg) {
if (state == State.DONE) {
return;
}
try {
blockingResponse.put(msg);
state = State.DONE;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
My Handler class for receive server response message like following;
public class FalconClientHandler extends SimpleChannelInboundHandler<ByteBuf> {
private ChannelHandlerContext ctx;
private Map<Long,ResponseFuture> responseFuture;
public synchronized void setResponseFuture(Map<Long,ResponseFuture> responseFuture) {
log.info("{} ResponseFuture setted",responseFuture.keySet());
this.responseFuture = responseFuture;
}
#Override
public void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf in) {
String input = in.toString(CharsetUtil.UTF_8);
String transactionKey = input.substring(52, 66).trim();
if(responseFuture.get(Long.valueOf(transactionKey))!=null)
responseFuture.get(Long.valueOf(transactionKey)).set(input);
else
log.info("[{}] Tcp Response map is empty",transactionKey);
}
}
When i run this code under high load like 30 transaction per second, tcp response returned from netty server but future get method received timeout.This situation not occuring every request for example %20 request is fail when 30 tps %50 request fail in 40 tps. What can be occur under load?
I am making a Curl post curl -X POST -d "dsds" 10.0.0.211:5201 to my Netty socket server but in my ChannelRead when I try to cast Object msg into FullHttpRequest It throws following exception.
java.lang.ClassCastException: io.netty.buffer.SimpleLeakAwareByteBuf cannot be cast to io.netty.handler.codec.http.FullHttpRequest
at edu.clemson.openflow.sos.host.netty.HostPacketHandler.channelRead(HostPacketHandler.java:42)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:334)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:326)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1320)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:334)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:905)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:123)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:563)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:504)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:418)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:390)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:742)
at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:145)
at java.lang.Thread.run(Thread.java:748)
Following is my Socket Handler class
#ChannelHandler.Sharable
public class HostPacketHandler extends ChannelInboundHandlerAdapter {
private static final Logger log = LoggerFactory.getLogger(HostPacketHandler.class);
private RequestParser request;
public HostPacketHandler(RequestParser request) {
this.request = request;
log.info("Expecting Host at IP {} Port {}",
request.getClientIP(), request.getClientPort());
}
public void setRequestObject(RequestParser requestObject) {
this.request = requestObject;
}
#Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
// Discard the received data silently.
InetSocketAddress socketAddress = (InetSocketAddress) ctx.channel().remoteAddress();
log.info("Got Message from {} at Port {}",
socketAddress.getHostName(),
socketAddress.getPort());
//FullHttpRequest request = (FullHttpRequest) msg;
log.info(msg.getClass().getSimpleName());
//((ByteBuf) msg).release();
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
// Close the connection when an exception is raised.
cause.printStackTrace();
ctx.close();
}
}
Pipeline:
public class NettyHostSocketServer implements IClientSocketServer {
protected static boolean isClientHandlerRunning = false;
private static final Logger log = LoggerFactory.getLogger(SocketManager.class);
private static final int CLIENT_DATA_PORT = 9877;
private static final int MAX_CLIENTS = 5;
private HostPacketHandler hostPacketHandler;
public NettyHostSocketServer(RequestParser request) {
hostPacketHandler = new HostPacketHandler(request);
}
private boolean startSocket(int port) {
NioEventLoopGroup group = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(group)
.channel(NioServerSocketChannel.class)
.localAddress(new InetSocketAddress(port))
.childHandler(new ChannelInitializer<SocketChannel>() {
#Override
public void initChannel(SocketChannel ch)
throws Exception {
ch.pipeline().addLast(
hostPacketHandler);
}
});
ChannelFuture f = b.bind().sync();
log.info("Started host-side socket server at Port {}",CLIENT_DATA_PORT);
return true;
// Need to do socket closing handling. close all the remaining open sockets
//System.out.println(EchoServer.class.getName() + " started and listen on " + f.channel().localAddress());
//f.channel().closeFuture().sync();
} catch (InterruptedException e) {
log.error("Error starting host-side socket");
e.printStackTrace();
return false;
} finally {
//group.shutdownGracefully().sync();
}
}
#Override
public boolean start() {
if (!isClientHandlerRunning) {
isClientHandlerRunning = true;
return startSocket(CLIENT_DATA_PORT);
}
return true;
}
#Override
public int getActiveConnections() {
return 0;
}
}
I also used wireshark to check If I am getting valid packets or not. Below is the screenshot of Wireshark dump.
Your problem is that you never decode the ByteBuf into an actual HttpRequest object which is why you get an error. You can't cast a ByteBuf to a FullHttpRequest object.
You should do something like this:
#Override
public void initChannel(Channel channel) throws Exception {
channel.pipeline().addLast(new HttpRequestDecoder()) // Decodes the ByteBuf into a HttpMessage and HttpContent (1)
.addLast(new HttpObjectAggregator(1048576)) // Aggregates the HttpMessage with its following HttpContent into a FullHttpRequest
.addLast(hostPacketHandler);
}
(1) If you also want to send HttpResponse use this handler HttpServerCodec which adds the HttpRequestDecoder and HttpResponseEncoder.
I have a nodeJS server setup to accept socket connections, this seems to work fine with my web applications.
Now I'm trying to setup the same server to accept socket connections from Kryonet library on Android, iOS(Though RoboVM) & Desktop.
Node setup:
gameserver.js
var server = app.listen(9999, function()
{
var host = server.address().address;
var port = server.address().port;
console.log('Gameserver listening at http://%s:%s', host, port);
});
//Socket IO stuff.
var io = require('socket.io').listen(server);
require('./live_game_api.js')(io);
live_api.js
module.exports = function(io)
{
io.sockets.on('connection', function(socket)
{
console.log('user connected to server.');
socket.on('test', function(msg){
console.log('message: ' + msg);
});
});
}
Then within my app I've got:
new Thread(new Runnable() {
#Override
public void run()
{
try
{
Client client = new Client();
client.start();
client.addListener(new Listener() {
public void connected(Connection connection) {
PolyUtils.log("Connected");
}
#Override
public void disconnected(Connection connection) {
TextNotifierController.getInstance().displayTextBottom(UPStrings.Disconnected_from_mothership);
super.disconnected(connection);
}
#Override
public void received(Connection connection, Object object) {
PolyUtils.log("received:" + connection.isConnected());
super.received(connection, object);
}
#Override
public void idle(Connection connection) {
super.idle(connection);
}
});
//192.168.1.11:9999
client.connect(SOCKET_CONNECTION_TIMEOUT, ServerController.SOCKET_DOMAIN, ServerController.SOCKET_NUMBER, -1);
Gdx.app.postRunnable(new Runnable() {
#Override
public void run() {
setupSocket();
}
});
}
catch(Exception exception)
{
Gdx.app.postRunnable(new Runnable() {
#Override
public void run() {
hasConnection = false;
TextNotifierController.getInstance().displayText(UPStrings.Error_connecting_to_mothership, TextNotifierController.nearBottomVec);
}
});
exception.printStackTrace();
}
}
}).start();
I get the following error when connecting on the client:
00:00 INFO: Connecting: /192.168.1.11:9999
java.net.SocketTimeoutException: Connected, but timed out during TCP registration.
I currently have a problem while working with Mina. I am able to create a NIOAcceptor and Connector and connect the client to the server. Upon session being created in the Server, it sends the handshake packet which in turn validates and sends back validation to the server to see if files are up-to-date, etc. The server receives this validation and correctly deciphers the packet and sends the packet to the Client to display the game window. However, after this initial connection, I can no longer send packets to the server via the Client.
ServerHandler:
#Override
public void sessionOpened(IoSession session) {
log.info("[Login] to [" + GameConstants.GAME_NAME + ": IoSession with {} opened", session.getRemoteAddress());
Client c = new Client(session);
connectedClients.add(session.getRemoteAddress().toString());
session.setAttribute(Client.KEY, c);
c.write(PacketCreator.getHandshake());
// c.write(PacketCreator.getPing());
}
#Override
public void messageReceived(IoSession session, Object message) {
PacketReader reader = new PacketReader((byte[]) message);
Client c = (Client) session.getAttribute(Client.KEY);
short header = reader.readShort();
PacketHandler handler = PacketProcessor.getHandler(header);
System.out.println("Received opcode: 0x" + Integer.toHexString(header).toUpperCase());
if (handler != null) {
handler.handlePacket(reader, c);
} else {
log.info("Received opcode: 0x" + Integer.toHexString(header).toUpperCase() + " with no handler.");
}
}
#Override
public void exceptionCaught(IoSession session, Throwable cause) {
System.out.println("session error");
}
#Override
public void sessionClosed(IoSession session) throws Exception {
System.out.println("Session closing: " + session.getRemoteAddress().toString());
connectedClients.remove(session.getRemoteAddress().toString());
Client c = (Client) session.getAttribute(Client.KEY);
if (c != null) {
c.disconnect();
c.dispose();
} else {
log.warn("Client is null in sessionClosed for ip {} when it shouldn't be", session.getRemoteAddress());
}
super.sessionClosed(session);
}
ClientHandler:
#Override
public void sessionOpened(IoSession session) {
System.out.println("Session opened: " + session);
Server s = new Server(session);
session.setAttribute(Server.KEY, s);
s.write(PacketCreator.getPong());
}
#Override
public void messageReceived(IoSession session, Object message) {
PacketReader reader = new PacketReader((byte[]) message);
Server s = (Server) session.getAttribute(Server.KEY);
short header = reader.readShort();
PacketHandler handler = PacketProcessor.getHandler(header);
if (handler != null) {
handler.handlePacket(reader, s);
} else {
log.info("Received opcode: 0x" + Integer.toHexString(header).toUpperCase() + " with no handler.");
}
}
#Override
public void exceptionCaught(IoSession session, Throwable cause) {
System.out.println("session error");
log.error("Exception caught in Server Handler: ", cause);
}
#Override
public void sessionClosed(IoSession session) throws Exception {
// TODO
System.out.println("session closed");
super.sessionClosed(session);
}
Client (NIOConnection class):
public static void connectToServer() throws Throwable {
NioSocketConnector connector = new NioSocketConnector();
connector.setConnectTimeoutMillis(1000 * 30); // 30 seconds
connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));
connector.setHandler(new ClientHandler());
IoSession session;
long startTime = System.currentTimeMillis();
for (;;) {
try {
ConnectFuture future = connector.connect(new InetSocketAddress("127.0.0.1", 9494)); // 24.7.142.74
future.awaitUninterruptibly();
session = future.getSession();
break;
} catch (RuntimeIoException e) {
log.error("Failed to connect", e);
Thread.sleep(5000);
}
}
session.getCloseFuture().awaitUninterruptibly();
}
Server (NIOAcceptor class):
private static void initializeLoginServer() {
PacketProcessor.registerHandlers();
acceptor = new NioSocketAcceptor();
// acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));// TODO: encoding/decoding packets
acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));
acceptor.getSessionConfig().setReadBufferSize(2048);
acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
acceptor.getSessionConfig().setTcpNoDelay(true);
acceptor.setHandler(new ServerHandler(1));
try {
acceptor.bind(new InetSocketAddress(GameConstants.SERVER_PORT));
} catch (Exception e) {
log.error("Could not bind. ", e);
}
log.info("Login Server: Listening on port " + GameConstants.SERVER_PORT);
}