Okay so here's my problem:
I'm building a netty 5 server in purpose of learning, but i came across this problem, Which is after binding problem:
So when i bind an port in netty 5 i do as this code:
bind(port).channel().closeFuture().sync();
Now the code that come after that line won't execute, code such as:
System.out.println("Server bound!");
How do i make it execute that code after binding?
The sync() call to the future object is a blocking call meaning it will wait for the socket to terminate. If you want some code to run after the bind then you will need to do something like:
ChannelFuture future = bind(port).channel().closeFuture();
System.out.println("Bound to port!");
future.sync(); // this will block until the port is shut down
Related
I am trying to develop a socket server supporting TCP sockets and WebSockets. I created two ServerBootsraps with their channels and handlers. I started them with different ports with (skipping unnecessary code parts because they are working ok)
...
ChannelFuture channelFuture = serverBootstrap.bind(port);
...
...
ChannelFuture channelFutureWebsocket = serverBootstrapWebSocket.bind(webSocketPort);
In the tutorials I've seen, they were all ending with serverBootstrap.bind(port).sync(); But If I end with sync, the server stops and waits for packets and I cannot start the other server (as expected). If I don't end with sync, the server runs ok but I am doubtful if it will cause an error in the future.
If my method, skipping sync(), is wrong, how can I run 2 different servers simultaneously?
The javadoc on the Future.sync says: "Waits for this future until it is done, and rethrows the cause of the failure if this future failed."
So what you want to do is get both futures and wait on them both instead of waiting on the 1st future before you've even had a chance to bind the 2nd server.
A simple way to wait on 2 futures is to use a while loop and check both futures using non-blocking methods
ChannelFuture bindFuture1 = bootstrap1.bind(port);
ChannelFuture bindFuture2 = bootstrap2.bind(port);
while (!bindFuture1.isDone() && !bindFuture2.isDone()) Thread.Sleep(INTERVAL);
//Evaluate both futures to see if there were any errors, wait for the other future to be done or do whatever else you need to based on your requirements.
I suggest you read up on futures to understand what the sync method does and why it's necessary. Also have a look here: Waiting on a list of Future
I'm trying to write an emulator for a single-threaded physical product. It accepts one long-lived connection and any other connections get a single error message (in the same thread).
I know I can use java.net with two threads:
Thread 1 - start ServerSocket on port XXXX and wait for accept(). For the first connection create a Socket and Thread #2, and for other connections produce an error message.
Thread 2 - process the Socket IO.
But how can I do it with one thread, so it behaves more like the physical product (ie. repeatedly attempting connections would starve the thread from dealing with the first connection)?
Trying not to use third-party libraries, but can do if that's the only option.
Thanks!
Unfortunately the common java.net.ServerSocket as well as the java.nio.channels.ServerSocketChannel only feature a blocking method to accept incoming connections. However the java.nio package features many other classes and methods to handle I/O-Operations in a single thread by multiplexing the opened channels.
This approach would still enforce a dedicated Thread for the accepting ServerSocketChannel but you could handle every accepted connection in a single thread.
In comparison the ServerSocket approach needs one new thread for each new connection.
Imgaine you connect 100 clients using a ServerSocket then you will end up with 101 thread. With a ServerSocketChannel you could end up using only 2 thread.
Still programming is often about a tradeoff between complexity/flexibility and performance. So keep that in mind.
A possible solution I could think of could look like this:
public static void main( String[] args ) throws IOException
{
int portNr = 8080;
ExecutorService es = Executors.newSingleThreadExecutor();
ChannelHandler ch = new ChannelHandler();
es.execute( ch );
// Starting server:
ServerSocketChannel serv = ServerSocketChannel.open();
// Bind socket to Port
serv.socket().bind(new InetSocketAddress(portNr));
while( serverAlive )
{
ch.addChannel(serv.accept());
}
serv.close();
}
How you actually process the new added SocketChannel depends on your application. And so does the ChannelHandler#addChannel method.
It seems like you should accept the single connection and then close the ServerSocket. Any future connect attempts will then get a connection refusal. When the long-lived connection ends, create a new ServerSocket, accept one more connection, ... Rinse and repeat.
EDIT If you have to deliver an error message as per your comment below, you have to accept the connection to send it over, and if you have to do I/O and accepting all in one thread you have to use java.nio.channels.ServerSocketChannel/SocketChannel, non-blocking mode, and a Selector.
Using a ServerSocket with one Thread is not a good idea at all. WHY?
you know socket.accept() waits till the next client connects, so the Thread is blocked and if you only have one Thread your whole Programm is blocked till a Client connects.
May you explain why you try to do it single threaded?
Looking at JDK 1.7 API. I cannot seem to be able to set a connection timeout on an AsynchonousSocketChannel. Is there anyway I can setup a connection timeout on such a channel?
Thanks.
The answer is: you can't.
The first thing to understand is how a TCP connect works. The kernel is sending SYN packets, backing off the time between each retry. This can be tuned via kernel parameters. An article covering this in detail (for linux) can be found here
To give you an idea of what's involved to implement your own shorter timeout for a socket connect is to put the socket in nonblocking mode, throw it in a select() with a timeout, then use getsockopt() to see what happened. This StackOverflow answer shows how this works.
With NIO.2, the connection process is handled for you using threads that you don't have access to. Unfortunately there's no way to tell it you want a shorter timeout on connects; it just calls your completion handler / notifies the Future when the connection either succeeds of fails (including timing out).
You do have the option of calling get(timeout, unit) on the returned Future, then cancelling the Futureif it times out ... but that means if you want the connect to be async you have to add another layer of threading / callbacks and may as well just implement your own async thing with nio.
One last thing worth mentioning since you're looking at async network stuff is that Netty does give this to you (using Nio):
Bootstrap bootstrap = new Bootstrap()
.group(new NioEventLoopGroup())
.channel(NioSocketChannel.class)
.remoteAddress(new InetSocketAddress(remoteAddress, port))
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, connectionTimeout);
ChannelFuture f = bootstrap.connect();
And you can register a listener with that ChannelFuture for a callback.
I have programmed a little Server with multiple Threads.
After a lot of hours (saidly currently I can't reproduce the problem) the server stops working. My code looks like this.
Thread2:
while(true)
{
System.out.println("Point 1");
Socket abc = serverSocket.accept();
System.out.println("Point 2");
connection = true;
}
Thread1 waits in a Thread.sleep(1000) loop and checks if connection is true. If so, it starts working, otherwise it prints "waiting". If connection aborts, it sets connection to false.
Now my Mainprogramm connects to the Server. Server prints
waiting
waiting
(and so on, till connection is established)
Point 1
Point 2
as it should.
Now after multiple hours of running, my client can still connect, it says connection established (done via clientSocket = new Socket(inetAddress,Integer.parseInt(port)); assumes connection established when this command succeeds without an exception).
After multiple hours of running Thread1 only prints "waiting", "waiting", no matter how often I connect with my client.
I'm stumped with it, because it happens only after multiple hours of running. Java version is
java version "1.7.0_07"
Java(TM) SE Runtime Environment (build 1.7.0_07-b10)
Are there any known issues with this version or where can be the mistake? Any clues how to reproduce the error?
Thanks for help.
If you do not synchronize the access to connection field and it is not a volatile field, then one Thread1 might not see that connection has changed in Thread2. This is how Java Memory Model works.
I finally solved the problem.
It is sufficient to have that code
InetAddress inetAddress = InetAddress.getByName("0.0.0.0");
serverSocket = new ServerSocket(39999,0,inetAddress);
and my Client says connected. There is no need for the a code like
Socket neuSocket = serverSocket.accept();
The whole thread got terminated because of a catch-block out of the while loop. Java is sometimes very confusing. If the thread has stopped with the declaration of the ServerSocket than it should not listen any longer on that socket.
I am from Ethiopia so i am sorry for my English
I was designing a muiltithread server/client application and the server has its own user interface that keep the list of all connected client the problem is
ss = new ServerSocket( port );
while (true) {
// Grab the next incoming connection
s = ss.accept();
ss.accept(); block the entire process and i am not able to access other functionalities of the server. the user interface of the server completly freez even though the server is accepting new clients and the client side is working perfectly.
so what shall i do to make the server accept new connection while processing other things
There are two (popular) ways of doing this:
A main thread containing a blocking loop waiting for clients. This main thread spawns a new Thread when a client is accepted.
Java New Input/Output. Everything is handled in the main thread. See http://rox-xmlrpc.sourceforge.net/niotut/index.html
Also: you point out your server application has a User Interface. A User Interface should be running in a different thread (the Event Dispatcher Thread, EDT) than the server.
you should spawn thread and call accept there
So Put this Listener ( in a method) and use TaskFactory. TaskFactory will execute the method in a separate thread and you will not have this problem