ConnectionListener events not firing

I have some weird issue going here, testing in the home on the LAN.



My client connects to the server, and the server’s connectionAdded() callback never gets called, nor does the client’s clientConnected() event.



I know I am connecting, because if I change the port the client is trying to connect on so that it does NOT match the one the server is listening on, the connection is refused. Similarly, if I quit the client app, low-level logging events are fired off on the server’s log – it sees the client dropping. However, neither side is ever thinking to call its application-level hooks.



FYI, I am using Network.createClient() and then asking that NetworkClient to connectToServer().



My server NetListener is registered on the Server:

mServer.addConnectionListener(mServerNetListener);



and my client’s NetListener is registered on the NetworkClient:

mNetworkClient.addClientStateListener(mClientNetListener);



What could be going wrong?

Could you give us listings for those two classes?



You can actually debug SpiderMonkey itself, which I’d recommend. Remember that its SpiderMonkey itself that does the connection brokering - if you set a breakpoint in the right place, you might be able to see why its not calling that method on your class.

If the connection listener never gets called… and presumably it is setup correctly (no code to see so I can’t tell for sure)… then it could be that the UDP message never makes it from the client to the server.



The client will send one UDP and one TCP message and if both don’t make it then the connection will hang. Currently the UDP message is not resent but it’s rare for the first UDP to be dropped anyway. More likely that a firewall is blocking it or something.



As the other poster mentions, seeing your setup code would be helpful.

Ok, the code is a little complex, contextually, but I zipped up a sparse subset of my com.resounding.apps folder and placed it here.



auth/AuthServer is the server, managing client connections from WorldServers via auth/WorldNetListener



world/WorldServer is the client app to the AuthServer, managing it connection to the AuthServer via world/AuthNetListener



If it helps you see past references to PlayerClients and ShipServers, I’ll explain that the overall network design I am working on is that of a scalable MMP game: AuthServer is the player login-point and lobby system and thus has com.jme3.network.Servers for both PlayerClients and WorldServers, and a WorldServer runs a shard of the game (thus it has a com.jme3.NetworkClient to the AuthServer and com.jme3.network.Servers to PlayerClients and other app instances called ShipServers).



This code fails to cause the clientConnected()/connectionAdded() methods to fire even when I run AuthServer and WorldServer on the same machine and change the AuthServer.DEFAULT_SERVER_ADDRESS to “localhost”. This makes me believe that firewall issues are not at play here.



The machine in use is an iMac running 10.6.8



Thanks in advance for any insights.



tone

I don’t have time right now to hunt through your code but if you can reduce it to a simpler test case then I can take a look.



Does the test chat server and test chat client work in your machine configuration?



I can say that normally this stuff works and there isn’t really anything complicated about just getting a connection to happen. I connect a hundred times a day when developing Mythruna both to my localhost server as well as the public server.



If you see logged connections and disconnections and don’t have your connection listener called then either the connection listener isn’t really added right or the connections are never fully setup. You can test that last one on the client if you try sending a message… it will block until the connection is fully setup. So if your app hangs then you know that the connection never really happens. The most likely cause of that is a missed UDP message.



Sometime recently I went round and round about this with another user on the end of some thread and it ultimately turned out to be something in his system configuration that was blocking a port. Pretty sure that was on Linux… on a Mac it seems less likely that you could get into that much trouble.

pspeed … I’ll keep cracking. TestChatClient connects easily to TestChatServer on my machine.



When I debug my app and set breakpoints in the server’s KernelAdapter, it blocks forever on kernel.read()



tone

Sure it does. It’s waiting for a message. That’s the way it works.



Can you at least post the code that shows how you create the server and how you connect the client to it?

Ok, here is a culled set of code from the serverside (I think perhaps my issue is client side, as I just tried a test wherein my server looked more like TestChatServer



AuthServer (extends SimpleApplication)

[java]

Server mWorldServers;





@Override

public void simpleRender(RenderManager rm) {

}





@Override

public void simpleInitApp() {



// create and start a server to accept and process WorldServer connections

try {

mWorldServers = Network.createServer(App.GAME_NAME, WORLD_NETWORK_VERSION, 52500, 52500);

mWorldServers.start();



new WorldNetListener(this);

} catch (IOException ex) {

getLogger().log(Level.SEVERE, "Cannot create server for WorldServers: "+ ex);

return;

} catch (KernelException ex) {

getLogger().log(Level.SEVERE, "Cannot start server for WorldServers: " + ex);

return;

}

}



public static void main(String[] args) throws Exception {

Serializer.registerClass(HandshakeMessage.class);

Serializer.registerClass(WorldStatusMessage.class);



AuthServer app = new AuthServer();



AppSettings settings = new AppSettings(true);

settings.setFrameRate(25);

settings.setRenderer(AppSettings.NULL);



// FIXME: strange way of setting null audio renderer…

settings.setAudioRenderer(null);



app.setShowSettings(false);

app.setPauseOnLostFocus(false);

app.setSettings(settings);

app.start();

}





[/java]



WorldNetListener implements MessageListener, ConnectionListener

[java]

AuthServer mAuthServer;

Server mWorldServers;



public WorldNetListener(AuthServer app) {

mAuthServer = app;

mWorldServers = app.mWorldServers;

mWorldServers.addConnectionListener(this);

mWorldServers.addMessageListener(this, HandshakeMessage.class, WorldStatusMessage.class);

}



// ConnectionListener callback – never fires

public void connectionAdded(Server server, HostedConnection client) {

}





// ConnectionListener callback – never fires

public void connectionRemoved(Server server, HostedConnection client) {

}



// MessageListener callback – never fires

public void messageReceived(HostedConnection source, Message message) {

}

[/java]

And, on the client side, culled down of course



[java]

public class WorldServer extends SimpleApplication {



NetworkClient mAuthServer;





@Override

public void simpleInitApp() {



// connect to AuthServer

try {

mAuthServer = Network.createClient();

new AuthNetListener(this);

mAuthServer.connectToServer("localhost", 52500, 52500);



} catch (IOException ex) {

getLogger().log(Level.SEVERE, "Cannot connect to AuthServer" + ex);

return;

}



}



public static void main(String[] args){



Serializer.registerClass(HandshakeMessage.class);

Serializer.registerClass(WorldStatusMessage.class);



WorldServer app = new WorldServer();



AppSettings settings = new AppSettings(true);

settings.setFrameRate(25);

settings.setRenderer(AppSettings.NULL);



// FIXME: strange way of setting null audio renderer…

settings.setAudioRenderer(null);



app.setShowSettings(false);

app.setPauseOnLostFocus(false);

app.setSettings(settings);

app.start();

}

}

[/java]



And its MessageHandler, AuthNetListener:

[java]



public class AuthNetListener implements MessageListener, ClientStateListener {



private WorldServer mWorldServer;

private Client mAuthServer;



public AuthNetListener(WorldServer worldServer) {

mWorldServer = worldServer;

mAuthServer = mWorldServer.mAuthServer;



// install self on the Client which connects us to AuthServer

mAuthServer.addClientStateListener(this);

mAuthServer.addMessageListener(this, HandshakeMessage.class);

}



// ClientStateListener… sadly, this never fires for some reason

public void clientConnected(Client client) {

HandshakeMessage msg = new HandshakeMessage(AuthServer.PLAYER_NETWORK_VERSION);

mAuthServer.send(msg);

}



// ClientStateListener… this never fires

public void clientDisconnected(Client client, DisconnectInfo info) {

}



// MessageListener… this never becomes relevant either

public void messageReceived(Object source, Message message) {



}

}

[/java]

re:

If you see logged connections and disconnections and don’t have your connection listener called then either the connection listener isn’t really added right or the connections are never fully setup. You can test that last one on the client if you try sending a message… it will block until the connection is fully setup. So if your app hangs then you know that the connection never really happens. The most likely cause of that is a missed UDP message.

Sometime recently I went round and round about this with another user on the end of some thread and it ultimately turned out to be something in his system configuration that was blocking a port. Pretty sure that was on Linux… on a Mac it seems less likely that you could get into that much trouble.


My connectToServer returns almost instantaneously. There is no sign that it fails to work.

I just now tried changing my port to the same one successfully used in TestChat* -- it did not help.

tone
@DulcetTone said:
My connectToServer returns almost instantaneously. There is no sign that it fails to work.


connectToServer() will return instantly always. Trying to send a message on the connection will block until it's fully setup.

It looks like you forget to call client.start()... unless I missed it somewhere.
1 Like

Last little clue…



If I run my client, it appears to run its connectToHost() command in quick order, though there is no indication whatsoever in the Server’s log that anything happened.



However, if I then kill the client app, there are log entries in the server’s log which indicate undeniably that it knew of the client’s connection in some manner:



[java]

Nov 19, 2011 1:48:05 PM com.jme3.network.kernel.tcp.SelectorKernel$SelectorThread connect

INFO: Hosting TCP connection:0.0.0.0/0.0.0.0:52500.

Nov 19, 2011 1:48:05 PM com.jme3.network.kernel.tcp.SelectorKernel$SelectorThread run

INFO: Kernel started for connection:0.0.0.0/0.0.0.0:52500.

Nov 19, 2011 1:48:05 PM com.jme3.network.kernel.udp.UdpKernel$HostThread connect

INFO: Hosting UDP connection:0.0.0.0/0.0.0.0:52500.

Nov 19, 2011 1:48:05 PM com.jme3.network.kernel.udp.UdpKernel$HostThread run

INFO: Kernel started for connection:0.0.0.0/0.0.0.0:52500.





THIS IS WHERE THE CONNECTION ATTEMPT OCCURS.

Nothing is output.

When the client process is killed, however, the following additional lines spill out:



Nov 19, 2011 1:49:01 PM com.jme3.network.kernel.tcp.SelectorKernel$SelectorThread cancel

INFO: Closing channel endpoint:NioEndpoint[1, java.nio.channels.SocketChannel[connected local=/192.168.1.101:52500 remote=/192.168.1.101:50502]].

Nov 19, 2011 1:49:01 PM com.jme3.network.base.DefaultServer connectionClosed

INFO: Connection closed:NioEndpoint[1, java.nio.channels.SocketChannel[closed]].

[/java]



Could this be an issue with GameName/client version number?



I’ll note that NetworkClient provides no means whatsoever to set the version number, as does Client, but neither did I see that the network code actually checks the game name or version number as the comments indicate. The default version number in some places is a playful 42, but may be in my NetworkClient a java-standard 0 which I cannot alter.



tone

@DulcetTone said:
I'll note that NetworkClient provides no means whatsoever to set the version number, as does Client, but neither did I see that the network code actually checks the game name or version number as the comments indicate. The default version number in some places is a playful 42, but may be in my NetworkClient a java-standard 0 which I cannot alter.


You specify the game server name and version when you create the NetworkClient... not when you connect it.
1 Like

Oh, and it definitely checks the version during connection. But the client has to send its connection message with that info and that happens when you START the connection. That gives you time to setup listeners, etc. before actually processing messages.

Yeah it looks like you arent starting your server. You need to catch an IOException when you start a server.

@ancalagon said:
Yeah it looks like you arent starting your server. You need to catch an IOException when you start a server.


He starts his server above. He doesn't start the client.

Yes you are right, sorry.

DOH!!! I never noticed that you had to start() a client. Of course you do – there’s that thread, I suppose.



Perhaps start() could be automatically called when a client connects?



I am now getting the connection stuff to work, and see that I need to use a different NetworkClient factory method to set the game name and version as I’d need. That’s given me room to run.



MANY THANKS for your time, pspeed.



tone

@DulcetTone said:
Perhaps start() could be automatically called when a client connects?


No, because you need to be able to setup stuff about the connection, etc. before calling start(). I know with NetworkClient you connect post-creation but really it's basically the same classes inside and you still might want to wait to start the connection until after you've done some other stuff. And you might not want to do that other stuff until you've verified that the host and port are correct or whatever.

In my case, I call Network.connect() and in that case it's vitally important to be able to add listeners before start().