Socket.io is one of several implementations for the websockets protocol and its main selling point (IMO) is its ease of use: you don't need to code keep-alive mechanisms or decide which transport is best, it does it for you.
So, to make it clear, socket.io doesn't replace the websocket protocol, it's a package that implements it for you.
You mentioned long-polling. That is one of the transports used by socket.io. Long Polling is HTTP based and it's basically request --> wait --> response and the wait isn't very long, as it can be dropped by load balancers on EOF or stale connections. Nevertheless, it's still useful when the websockets protocol (TCP based) isn't available and socket.io automatically re-establishes the connection for you. Notice that websockets is a relatively new protocol, ratified in 2011, so older browsers don't support it. Well, socket.io detects that and then resorts to long polling, so you don't have to "worry" about it.
A websocket connection starts with HTTP, listening on the same port. For example, http://localhost:8080 (just a silly example). Then, when it's possible, socket.io switches to ws://localhost:8080 for you.
I never had problems with network topology challenges when using socket.io, as when the HTTP port is available and using long polling / websockets is possible, it just worked for me.
One of the libraries with fallback implementation, as you mentioned, is netty-socket.io. Notice how it configures the two transports:
public class Configuration {
private ExceptionListener exceptionListener = new DefaultExceptionListener();
private String context = "/socket.io";
private List<Transport> transports = Arrays.asList(Transport.WEBSOCKET, Transport.POLLING);
private int bossThreads = 0; // 0 = current_processors_amount * 2
private int workerThreads = 0; // 0 = current_processors_amount * 2
The complete code can be found here.
Node JS has also libraries for websockets, and I mention it here just to clarify that long polling and websockets aren't the only two available transports (might be the only ones in Java):
io.set('transports', [ // enable all transports (optional if you want flashsocket)
'websocket'
, 'flashsocket'
, 'htmlfile'
, 'xhr-polling'
, 'jsonp-polling'
]);
In a nutshell, socket.io attempts to make things as easy as possible for you, including not having to worry about what transports to use, as it's done under the hood for you, yet still configurable if you want.
I hope this brief explanation helps you!