Can only connect to server via LAN (and other questions)

Hello,



As this is my first post I just wanted to say a big thank you to the jmonkeyengine guys for all the work they have done. I only picked it up a few weeks ago and was surprised how easy it was to build a 3D world with water/light/random terrain/etc which I could explore.



Anyway I’ve started looking into the multiplayer side of things, I figured it would be easier to get this working first before I continued doing any work on my project. The basic aim is to be able to have 4 players in a world.



So I created a server, using spider monkey, and have been following articles and tutorials online about what data should be sent to and from the server, how to combat cheating, client predictions and lag compensation.



At the moment the client connects to the server and every time a user presses a button this is sent to the server (eg when the forward button is pressed and again when it is released). The server, which extends SimpleApplication, has a copy of the map loaded, runs the physics and every time the users position changes sends it back to the client.



At the moment, for simplicity sakes, i’m not doing any client prediction or lag compensation. So my first question (of many, sorry) is should the server be doing all the physics simulations? I intent to add client prediction later, but is it good practise to have the server doing all the grunt work with collision detections.



Secondly how often should the server be sending the client a position update, at the moment it’s doing it on every iteration of simpleUpdate but i’ve read in some articles that the server should send an update at fixed intervals, e.g every 50ms.



So at the moment I can connect to my server, over LAN, have the server run all the physics and update the client constantly and the game runs smoothly. However this is because it is connecting over LAN, I wanted to connect over the internet to see how bad the lag is and see what kind of lag compensation I need however if I use my IP in:



[java]client = Network.connectToServer("testGame", 1, "<my ip>", 52868);[/java]



It won’t connect and throws an error with


java.net.ConnectException: Connection refused
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:351)
at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:213)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:200)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:432)
at java.net.Socket.connect(Socket.java:529)
at java.net.Socket.connect(Socket.java:478)
at java.net.Socket.(Socket.java:375)
at java.net.Socket.(Socket.java:218)
at com.jme3.network.kernel.tcp.SocketConnector.(SocketConnector.java:62)
at com.jme3.network.Network.connectToServer(Network.java:166)
at com.jme3.network.Network.connectToServer(Network.java:142)
at hello.MyGame.simpleInitApp(MyGame.java:106)
at com.jme3.app.SimpleApplication.initialize(SimpleApplication.java:230)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.initInThread(LwjglAbstractDisplay.java:124)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:200)
at java.lang.Thread.run(Thread.java:680)


So my final question is, any ideas what's causing this? My guess is it's a problem with my firewall/router (BT HomeHub and macbook pro w/ Lion)
But is there anything I need to configure on the server to allow me to connect over the Internet? I can post code if people want to see it.

Sorry for the monolithic post but I wanted to get these things sorted in my mind before I waste hours doing it wrong.

tl;dr

1) Should the server run all the physics
2) How often should the server update the clients
3) Cannot connect to my server over the Internet, just Lion

Is the first error in the quoted log the first error that you saw?



I think I’ve seen a similar error before. There’s a particular player who connects to my server and something goes sour with his connection. From then on I get these messages. They are harmless other than that they dirty up the logs and console… but I’d like to know why they happen and attempt a fix.



It’s basically saying that the network layer received a packet over UDP but that it doesn’t contain a full message. This shouldn’t happen really because UDP packets are delivered in total or not at all. I’ve often suspected that something else is at play.

  1. physics : sent only the data that were altered in the world.



    2)

    a) not only that, the question is in what type of messages will you have.
  2. position / velocity ( every 100-200 ms)
  3. physics (every 500-700ms).
  4. damage (300-400ms)




  5. because ipv4 sucks, nat forbids you from delivering data to your machine. you have to go to your router and tell it to redirect data to your machine. Too bad that 99% of users dont know how to do that.

For your first questions… what kind of game is it? A lot of that depends.



For the last question, as tralala indicates, your firewall needs to know how to route the connections to the server that sits behind it. The internet sees you as one address and your LAN sees you as another. For whatever ports your server opens, you need to forward those through your firewall/router. Note that this is only a requirement for the server… clients through a NAT should work just fine as long as they find the server.

Wow thanks for the quick replies.


tralala said:
you have to go to your router and tell it to redirect data to your machine.


By this do you mean I should just open up the required ports? Or is there something else I should be doing?


pspeed said:
For your first questions... what kind of game is it? A lot of that depends.


The idea at the moment is a 3rd person hack/slash game focusing on exploration of random worlds in a party of 4 people. Think spiral knights/torghlight esq

re: The firewall/router…



For example, I host a mythruna public server through my cable connection. I have a machine on my LAN running the server and listening on port 4234. In my router, I’ve configured it to forward any UDP and TCP data for port 4234 to go directly to that machine on my LAN. So when a user connects to my cable modem on :4234 they are actually connecting to a machine on my LAN with the NAT firewall making sure the packets go back and forth like they should. Your router should have some way of configuring this.



re: network architecture…



If you are not relying on the “twitch factor” like a FPS then you can get away with a slightly simpler architecture since at best you only do prediction on the client.



Still, I’m rather fond of the UDP state updates at fixed intervals. The key here is that you are still sending the same number of updates but you are bundling them into less frequent messages. So if your physics runs at 60 FPS and you are only sending state messages at 20 FPS (50 ms) then you’d be sending three updates per message. You can do this with the state that the client sends to the server and also the state that the server sends to the client.



Though there is nothing wrong with blasting every state update like you are… though I’d hope it’s UDP and not TCP for these updates. I do this with Mythruna right now… I’ve designed to bundle but I know on at least one direction that I’m not doing it.



You sound like you already read these but I’m including them just in case:

http://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking

http://developer.valvesoftware.com/wiki/Latency_Compensating_Methods_in_Client/Server_In-game_Protocol_Design_and_Optimization



For a non-FPS game you can probably ignore the server side prediction stuff.



And yeah, I think the server should be doing the physics so that it can be authoritative. It’s your best defense against rampant cheating or just strange paradoxes. The client can still do it too for prediction but the server is “law” if there are conflicts.

pspeed said:
For example, I host a mythruna public server through my cable connection. I have a machine on my LAN running the server and listening on port 4234. In my router, I've configured it to forward any UDP and TCP data for port 4234 to go directly to that machine on my LAN. So when a user connects to my cable modem on :4234 they are actually connecting to a machine on my LAN with the NAT firewall making sure the packets go back and forth like they should. Your router should have some way of configuring this.


Is there a particular name for this method so I can google how to do it on my router, it sounds like port forwarding to me.

At the moment it's TCP, but the only reason it's that was so I could check the server and client were working properly and know all the packets were being received. I will be switching to UDP soon and implementing the basic TCP-esq reliability features myself on top of UDP.

With respect to sending messages at fixed intervals I think i'm going to get my server to work over the Internet first, determine how bad the lag is then experiment to find a solution which works best for my game.

Also thanks for those links, I hadn't though to read anything from Valve but I will definitely have a good look through them. I've been mainly working from this article:
http://gafferongames.com/game-physics/networked-physics/
plus a few others.

Port forwarding should be pretty good. Most routers that I’m familiar with have a configuration web page you can hit and set these things.



I wouldn’t implement your own TCP on top of UDP… you might as well just use TCP. UDP is good for the data that is stale the moment the next packet comes in.



There are two basic schemes: TCP and only send changes in state and just deal with the extra lag through client prediction. UDP always send the latest state for everything the player can see… if a packet gets lost then there’s no big deal because another one is already on its way. This second case is what the Valve articles describe.



They each have their trade-offs.

SUCCESS!



Thank you very much, I can now connect to the server through the internet, just had to shout and scream at my router until it behaved.



Of coure now I have a new problem, when I start the server I get a continuous stream of error messages


Aug 18, 2011 2:15:01 PM com.jme3.network.base.KernelAdapter reportError
SEVERE: Unhandled error, endpoint:UdpEndpoint[1, /94.65.222.168:22000], context:Envelope[UdpEndpoint[1, /94.65.222.168:22000], unreliable, 30]
java.lang.RuntimeException: Envelope contained incomplete data:Envelope[UdpEndpoint[1, /94.65.222.168:22000], unreliable, 30]
at com.jme3.network.base.KernelAdapter.createAndDispatch(KernelAdapter.java:209)
at com.jme3.network.base.KernelAdapter.run(KernelAdapter.java:260)
Aug 18, 2011 2:15:05 PM com.jme3.network.base.KernelAdapter reportError
SEVERE: Unhandled error, endpoint:UdpEndpoint[2, /119.92.74.123:17872], context:Envelope[UdpEndpoint[2, /119.92.74.123:17872], unreliable, 103]
java.lang.RuntimeException: Envelope contained incomplete data:Envelope[UdpEndpoint[2, /119.92.74.123:17872], unreliable, 103]
at com.jme3.network.base.KernelAdapter.createAndDispatch(KernelAdapter.java:209)
at com.jme3.network.base.KernelAdapter.run(KernelAdapter.java:260)
Aug 18, 2011 2:15:05 PM com.jme3.network.base.KernelAdapter reportError
SEVERE: Unhandled error, endpoint:UdpEndpoint[3, /202.89.169.202:20142], context:Envelope[UdpEndpoint[3, /202.89.169.202:20142], unreliable, 67]
java.lang.RuntimeException: Envelope contained incomplete data:Envelope[UdpEndpoint[3, /202.89.169.202:20142], unreliable, 67]
at com.jme3.network.base.KernelAdapter.createAndDispatch(KernelAdapter.java:209)
at com.jme3.network.base.KernelAdapter.run(KernelAdapter.java:260)
Aug 18, 2011 2:15:06 PM com.jme3.network.base.KernelAdapter reportError
SEVERE: Unhandled error, endpoint:NioEndpoint[5, java.nio.channels.SocketChannel[connected local=/192.168.1.70:52868 remote=/91.138.245.172:54682]], context:Envelope[NioEndpoint[5, java.nio.channels.SocketChannel[connected local=/192.168.1.70:52868 remote=/91.138.245.172:54682]], reliable, 108]
java.lang.RuntimeException: Error deserializing object
at com.jme3.network.base.MessageProtocol.createMessage(MessageProtocol.java:186)
at com.jme3.network.base.MessageProtocol.addBuffer(MessageProtocol.java:162)
at com.jme3.network.base.KernelAdapter.createAndDispatch(KernelAdapter.java:196)
at com.jme3.network.base.KernelAdapter.run(KernelAdapter.java:260)
Caused by: com.jme3.network.serializing.SerializerException: Class not found for buffer data.
at com.jme3.network.serializing.Serializer.readClassAndObject(Serializer.java:334)
at com.jme3.network.base.MessageProtocol.createMessage(MessageProtocol.java:182)
... 3 more


However my client can still connect and the server will still run the physics and update the client correctly. Any thoughts?

Though… really it might be masking a different problem…



Since: java.lang.RuntimeException: Error deserializing object is for the reliable channel which should be unaffected by the other stuff.



It seems like you haven’t registered the same classes on client and server in exactly the same order. In other words, the other end sent a message that this end doesn’t have a class registered for.

I’m getting al these errors before a client connects

Can you try a different port? I think you are way up in the ethereal ports and so are potentially getting network garbage… though the TCP errors are troubling.



Trying something like 4000 or 4242 or something.

I will be switching to UDP soon and implementing the basic TCP-esq reliability features myself on top of UDP.

You will re-implemented the wheel to reach a slower type connection ? why do that ?

UDP is good for the data that is stale the moment the next packet comes in.

For transmiting physics you will need tcp, because you need an 100% reliable way to transmit data that always must reach at same order.
For transmiting position / velocity you do need udp, because you dont care about the past position of the player because of a lost packet since you have a new packet that tells you where he is.

“For transmiting physics”



Which physics? You need to make sure the inputs get there from the client reliably but presuming that there is minimal client-side prediction of physics then all other state coming from the server is transient state… just position data, really. Even if you try to do some client-side prediction, as long as the server to client state includes position then the next packet trumps the last.

Switched to port 4242 and that seems to have fixed it.



Thanks for all the help, i’m sure i’ll have more questions soon