I'm making my first steps with netty and I'm wondering about the following behaviour of netty:
When i use the following Handler:
public class SimpleServerHandler extends ChannelInboundHandlerAdapter {
DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
#Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf inBuffer = (ByteBuf) msg;
String received = inBuffer.toString(CharsetUtil.UTF_8);
System.out.println(dateFormat.format(new Date()) + " Server received: " + received);
ctx.writeAndFlush(Unpooled.copiedBuffer("Hello " + received, CharsetUtil.UTF_8));
}
#Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
And I then send a TCP packet with "Packet Sender" I get three packets
the first is from the "packet sender" to the server,
the second is the response from the server (so something like "Hello testtest")
and then .. and I don't know where this packet comes from:
a third one from the server to the "packet sender", without any content
My Server java is:
public class MainNettyApplicationServer {
public static void main(String[] args) throws InterruptedException {
EventLoopGroup group = new NioEventLoopGroup();
try {
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(group);
serverBootstrap.channel(NioServerSocketChannel.class);
serverBootstrap.localAddress(new InetSocketAddress("10.0.0.2", 11111));
serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new SimpleServerHandler());
}
});
ChannelFuture channelFuture = serverBootstrap.bind().sync();
System.out.println("Server started.");
channelFuture.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
group.shutdownGracefully().sync();
}
}
}
Related
I try to create a client which will retry connect when previous connection timeout. This program tries to connect to localhost:8007 which port 8007 is without any service, so the program will retry after connection time out. But this code will free after running for a while. The program freezes when there are about 3600 threads. I expect it will continue to retry rather than it will freeze.
The standard output's last output is "retry connect begin".
Does anyone know the reason why it will freeze?
JProfiler: program's Thread statistic, shows 2 threads are blocked on java.lang.ThreadGroup:
JProfiler showing program's Thread statistic
public final class EchoClient2 {
static final boolean SSL = System.getProperty("ssl") != null;
static final String HOST = System.getProperty("host", "127.0.0.1");
static final int PORT = Integer.parseInt(System.getProperty("port", "8007"));
static final int SIZE = Integer.parseInt(System.getProperty("size", "256"));
public static void main(String[] args) throws Exception {
// Configure SSL.git
EchoClient2 echoClient2 = new EchoClient2();
echoClient2.connect();
}
public void connect() throws InterruptedException {
final SslContext sslCtx;
// Configure the client.
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioSocketChannel.class)
.option(ChannelOption.TCP_NODELAY, true)
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10)
.handler(new ChannelInitializer<SocketChannel>() {
#Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
//p.addLast(new LoggingHandler(LogLevel.INFO));
p.addLast(new EchoClientHandler());
}
});
// Start the client.
ChannelFuture f = b.connect(HOST, PORT);
f.addListener(new ConnectionListener());
System.out.println("add listener");
f.sync();
System.out.println("connect sync finish");
// Wait until the connection is closed.
f.channel().closeFuture().sync();
System.out.println("channel close");
} finally {
// Shut down the event loop to terminate all threads.
//group.shutdownGracefully();
}
}
}
public class ConnectionListener implements ChannelFutureListener {
#Override
public void operationComplete(ChannelFuture channelFuture) throws Exception {
System.out.println("enter listener");
EventLoop eventLoop = channelFuture.channel().eventLoop();
eventLoop.schedule(new Runnable() {
#Override
public void run() {
try {
System.out.println("retry connect begin");
new EchoClient2().connect();
System.out.println("retry connect exit");
} catch (InterruptedException e) {
System.out.println(e);
e.printStackTrace();
}
}
}, 10, TimeUnit.MILLISECONDS);
System.out.println("exit listener");
}
}
I am trying to recognize any exception after client receive or send message to server or from server. And If any exception happens, I want to close connection and say that "Connection has been closed because of 'this' exception" etc.
CONNECTION
public static boolean connect(Host host, String message, int mode) throws Exception {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap clientBootstrap = new Bootstrap();
clientBootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 100);
clientBootstrap.group(group);
clientBootstrap.channel(NioSocketChannel.class);
clientBootstrap.remoteAddress(new InetSocketAddress(host.getIp(), host.getPort()));
clientBootstrap.handler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel socketChannel) {
//TODO, TIMEOUT BILGISI ILE DOLDUR BURAYI
//socketChannel.pipeline().addLast(new ReadTimeoutHandler(1));
//socketChannel.pipeline().addLast("idleStateHandler", new IdleStateHandler(2, 2, 4));
socketChannel.pipeline().addLast(new FalconClientHandler(host, message, mode));
}
});
ChannelFuture channelFuture = clientBootstrap.connect().sync();
//TODO I NEED TO CATCH IT SOMEWHERE IN HERE
channelFuture.channel().closeFuture().sync();
return true;
} catch (Exception e) {
System.err.println("Connection timed out --> " + e);
host.setActive(false); //connection kurulamadı demektir. Bir sonraki mesaj geldiğinde bu hostun açılıp açılmadığı denenecek.
return false;
} finally {
group.shutdownGracefully().sync();
if (mode == 0) { //arka planda sunucu hep ayakta olmalı. Mode 0 da asla bağlantı kesilmemeli. Kesiliyorsa host kapanmıştır.
host.setActive(false);
return false;
}
}
}
CATCHING EXCEPTION
#Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)throws Exception {
cause.printStackTrace();
//CLOSE CONNECTION AND I HAVE TO PASS THE INFORMATION WHY CONNECTION CLOSED
ctx.close();
}
READ FUNCTION
#Override
public void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf in) {
InetSocketAddress socketAddress = (InetSocketAddress) channelHandlerContext.channel().remoteAddress();
InetAddress inetaddress = socketAddress.getAddress();
String ipAddress = inetaddress.getHostAddress(); // IP address of client
TCPHandshakeMessage tcpMessage;
byte[] signal;
String input = in.toString(CharsetUtil.US_ASCII);
/*
* mode 0 -> Amaç sunucuların ayakta olup olmadığını anlamak
* mode 1 -> Amaç sunuculara mesaj göndermek
* */
if(this.mode == 1){ //MODE 1 BAŞLANGICI
//I WRITE THIS ON PURPOSE
double x = 12 / 0;
System.err.println("MESSAGE SENT TO " + message + " IP : " + ipAddress);
this.host.setActive(true);
//TODO TCP MESSAGE SINIFINI KULLAN
signal = message.getBytes();
sendMessage(channelHandlerContext, signal);
/*try {
}catch (Exception e){
System.out.println("An Error Occured " + e);
}finally {
channelHandlerContext.channel().close();
}*/
}
}
Should I use channelFuture.addListener() in CONNECTION area?
Thanks.
If it is HTTP 1.1 request you can handle the exception as follows:
#Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
ctx.writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR))
.addListener(ChannelFutureListener.CLOSE);
LOG.error("Error occured", cause);
}
ChannelFutureListener.CLOSE listener will close the connection after writeAndFlush succeeds
I'm trying to write a JavaScript server running on NodeJS using Socket.io that communicates with the client which is written in JAVA.
I have no problem with the server side because I try it with a JavaScript client, so I assumed that the problem came from my java client.
I have this error on my client side :
io.socket.SocketIOException: Error while handshaking
at io.socket.IOConnection.handshake(IOConnection.java:322)
at io.socket.IOConnection.access$600(IOConnection.java:39)
at io.socket.IOConnection$ConnectThread.run(IOConnection.java:199)
Caused by: java.io.IOException: Server returned HTTP response code: 400 for URL: http://localhost:8000/socket.io/1/at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at io.socket.IOConnection.handshake(IOConnection.java:313)
This is my code(client side) :
public class BasicExample implements IOCallback {
private SocketIO socket;
public static void main(String[] args) {
try {
new BasicExample();
} catch (Exception e) {
e.printStackTrace();
}
}
public BasicExample() throws Exception {
socket = new SocketIO();
socket.connect("http://localhost:8000", this);
// Sends a string to the server.
socket.send("Hello Server");
// Emits an event to the server.
socket.emit("event", "ILYES");
}
#Override
public void onMessage(JSONObject json, IOAcknowledge ack) {
try {
System.out.println("Server said:" + json.toString(2));
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onMessage(String data, IOAcknowledge ack) {
System.out.println("Server said: " + data);
}
#Override
public void onError(SocketIOException socketIOException) {
System.out.println("an Error occured");
socketIOException.printStackTrace();
}
#Override
public void onDisconnect() {
System.out.println("Connection terminated.");
}
#Override
public void onConnect() {
System.out.println("Connection established");
}
#Override
public void on(String event, IOAcknowledge ack, Object... args) {
System.out.println("Server triggered event '" + event + "'");
}
}
Here is my client side source code:
public class Client
{
Server server;
Logger logger;
ChannelHandlerContext responseCtx;
public Client(String host, int port, int mode, String fileName)
{
server=null;
EventLoopGroup group = new NioEventLoopGroup();
try
{
Bootstrap b = new Bootstrap();
b.group(group);
b.channel(NioSocketChannel.class);
b.remoteAddress(new InetSocketAddress(host, port));
b.handler(new MyChannelInitializer(server, mode,fileName));
ChannelFuture f = b.connect().sync();
f.channel().closeFuture().sync();
System.out.println("client started");
}
catch (InterruptedException e)
{
e.printStackTrace();
}
finally
{
try {
group.shutdownGracefully().sync();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Calendar endTime=Calendar.getInstance();
System.out.println("client stopped "+endTime.getTimeInMillis());
}
}
public static void main(String[] args) throws Exception
{
#SuppressWarnings("unused")
Client c=new Client("localhost",1234,MyFtpServer.SENDFILE,"D:\\SITO3\\Documents\\Xmas-20141224-310.jpg");
}
}
Here is my File Transfer Complete Listener source code:
public class FileTransferCompleteListener implements ChannelFutureListener
{
Server server;
public FileTransferCompleteListener(Server server)
{
this.server=server;
}
#Override
public void operationComplete(ChannelFuture cf) throws Exception
{
Calendar endTime=Calendar.getInstance();
System.out.println("File transfer completed! "+endTime.getTimeInMillis());
if(server!=null)
server.stop();
else
cf.channel().close();
}
}
Here is the execution result:
File transfer completed! 1451446521041
client started
client stopped 1451446523244
I want to know why it takes about 2 second to close connection.
Is it any way to reduce it?
thank you very much
Take a look at shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit), you can specify the quietPeriod, by default it is a couple of seconds.
I’m not sure what the implications are if you shorten this.
I'm doing a mobile app for a website and they use Socket.io and Websocket to comunicate.
I'm using socket.io-java-client on Android to connect to the Socket.io server, the problem is, i don't know how to set custom headers / cookies with it.
here is how the code looks like:
public void runIO(){
try {
SocketIO socket = new SocketIO("http://192.168.1.60:1337");
socket.connect(new IOCallback() {
#Override
public void onMessage(JSONObject json, IOAcknowledge ack) {
try {
System.out.println("Server said:" + json.toString(2));
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onMessage(String data, IOAcknowledge ack) {
System.out.println("Server said: " + data);
}
#Override
public void onError(SocketIOException socketIOException) {
System.out.println("an Error occured");
socketIOException.printStackTrace();
}
#Override
public void onDisconnect() {
System.out.println("Connection terminated.");
}
#Override
public void onConnect() {
System.out.println("Connection established");
}
#Override
public void on(String event, IOAcknowledge ack, Object... args) {
System.out.println("Server triggered event '" + event + "'");
}
});
// This line is cached until the connection is establisched.
socket.send("Hello Server!");
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
In fact there are simple functions that can be used to set headers before connection:
addHeader(String key, String value) and setHeaders(Properties headers)
You can also use SocketIO(final String url, Properties headers) (instead of SocketIO(final String url) that i was using):
// Haeader Properties initiation
private Properties headers = new Properties();
and then for exemple to set cookies:
headers.setProperty("Cookie","key=data;key2=data2");
Finally when connecting replace
this.socket = new SocketIO(val);
by
this.socket = new SocketIO(val,this.headers);