Networking code
Networking code
Obviously UDP, but for the networking code itself I would suggest we use auswaschbars UDP classes in spring as a starting point. In the last few months the spring network classes have been subject to heavy refactorign and cleaning up by him with the aim that they're portable enough to be moved out into a dedicated server program so autohosts don't have to handle the spring game rendering and simulation and can just handle the traffic itself.
- zuzuf
- Administrateur - Site Admin
- Posts: 3281
- Joined: Mon Oct 30, 2006 8:49 pm
- Location: Toulouse, France
- Contact:
hm interesting, this can be useful indeed.
Currently we only have a working TCP class (which should handle both IPv6 and IPv4) which has been successfully tested on Linux and windows with IPv4.
I'll have a look at Spring's networking classes.
As far as UDP & TCP are concerned, UDP is faster, so it'll be used for time critical stuffs but it's not "reliable" (you don't know if the data you send have been received or not), so for sync critical stuffs, TCP should be better (ie: a unit death cannot be skipped otherwise the game will lose synchronization).
We could use TCP for chat, sync critical events, file transfer, etc... and UDP for normal syncing.
Currently we only have a working TCP class (which should handle both IPv6 and IPv4) which has been successfully tested on Linux and windows with IPv4.
I'll have a look at Spring's networking classes.
As far as UDP & TCP are concerned, UDP is faster, so it'll be used for time critical stuffs but it's not "reliable" (you don't know if the data you send have been received or not), so for sync critical stuffs, TCP should be better (ie: a unit death cannot be skipped otherwise the game will lose synchronization).
We could use TCP for chat, sync critical events, file transfer, etc... and UDP for normal syncing.
=>;-D Penguin Powered
I disagree to use only UDP protocol for communications. Like I explained in another topic, the UDP packets could be lost and this is a "normal" behaviour. We must guarantee that all important exchanged information is received. We can use UDP for sending some information less important but, except if I missed the topic, we did not define the exchanged information, the architecture (server-client? p2p? etc.). Before the choice of the used communication protocol, we need to define the exchanged data and following the volume of and importance of information, we decide the protocol and the architecture
Best regards,
Best regards,
"same shit, different day" Stephen King's book "Dreamcatcher"
- zuzuf
- Administrateur - Site Admin
- Posts: 3281
- Joined: Mon Oct 30, 2006 8:49 pm
- Location: Toulouse, France
- Contact:
UPnP also works with TCP, so I don't see any problem to use TCP.
I agree that we'll need TCP for things that need to be received (unless we find something better but really I doubt we will).
So what kind of data do we need to send and how ?
Since every client will be running the simulation for its units and weapons, there is no privileged machine that could be a server more than another client.
So I think a p2p network would be better, with the possibility to use a "fast node" to relay data from clients that have low bandwidth.
The data we need to send are exactly what Cire described earlier and the same thing for weapon data.
I agree that we'll need TCP for things that need to be received (unless we find something better but really I doubt we will).
So what kind of data do we need to send and how ?
Since every client will be running the simulation for its units and weapons, there is no privileged machine that could be a server more than another client.
So I think a p2p network would be better, with the possibility to use a "fast node" to relay data from clients that have low bandwidth.
The data we need to send are exactly what Cire described earlier and the same thing for weapon data.
=>;-D Penguin Powered
A p2p tcp system si worse for NAT issues.
Combined with the fact UPnP is turned off by default in routers for security reasons, and hole punching doesn't work with TCP. That and most games use UDP anyway, and packets that don't arrive can be re-requested, otherwise TCP wouldn't work at all (Afterall they both have the same problem at lower levels of the network stack).
The content of the network itself shouldn't be affected by this though as either way the transport method is rather irrelevant the data will still be the same.
Combined with the fact UPnP is turned off by default in routers for security reasons, and hole punching doesn't work with TCP. That and most games use UDP anyway, and packets that don't arrive can be re-requested, otherwise TCP wouldn't work at all (Afterall they both have the same problem at lower levels of the network stack).
The content of the network itself shouldn't be affected by this though as either way the transport method is rather irrelevant the data will still be the same.
-
- Posts: 13
- Joined: Wed Nov 21, 2007 2:38 am
- Location: America
- Contact:
computer that "hosts" the game that the others join is automatically the server of it in a general sense since they picked a lot of the settings for the game such as map, metal, energy, etc.. easier to program and troubleshoot all the clients if they sync to that 1 computer that started the game than all of them syncing data to all the others like in P2P. its a waste a bandwidth, and wouldn't it be more work to do P2P than client/server? only thing is for players more than 2.
if player that hosted game loses, and quits, "server" must be passed to the next computer (in order of joining? the game)
for data: wouldn't it be just syncing the arrays that already exist from when a game is single player, between all the computers? then add on chat? things i think that must arrive on time are
unit position
unit health
unit location
chat
weapon location (where a emg or laser or rocket, etc. is currently)
things that should arrive but if they didnt arrive wouldnt cause balance problems but simply graphical issues are
unit direction
unit scripting such as turret direction
weapon direction
if player that hosted game loses, and quits, "server" must be passed to the next computer (in order of joining? the game)
for data: wouldn't it be just syncing the arrays that already exist from when a game is single player, between all the computers? then add on chat? things i think that must arrive on time are
unit position
unit health
unit location
chat
weapon location (where a emg or laser or rocket, etc. is currently)
things that should arrive but if they didnt arrive wouldnt cause balance problems but simply graphical issues are
unit direction
unit scripting such as turret direction
weapon direction
Last edited by sieistganzfett on Sat Dec 15, 2007 9:06 pm, edited 1 time in total.
Please do not take this as an attack against you as its not what I mean, but you obviously have very little knowledge of network programing. As already started UDP traffic isn't guarenteeed, and thus some type of ack would be needed, it is however smarter to use UDP then a straight TCP, because TCP often becomes blocked, and dealing with blocking in code isn't pretty.western wrote:I disagree to use only UDP protocol for communications. Like I explained in another topic, the UDP packets could be lost and this is a "normal" behaviour. We must guarantee that all important exchanged information is received. We can use UDP for sending some information less important but, except if I missed the topic, we did not define the exchanged information, the architecture (server-client? p2p? etc.). Before the choice of the used communication protocol, we need to define the exchanged data and following the volume of and importance of information, we decide the protocol and the architecture
Best regards,
Its much more faster/smarter to do something like:
Tick:
dirty units-> distrubute and send data:
client 1, client 2, host
wait:
client 1 sends back ack
host send back ack
host signals that its ready to goto next tick:
we report to host that client 2 hasn't responed to our data sent
host orders us to send again, we do so, in which case:
client can respond or not, if not we could route data through client 1, or host to client 2, once ack is received we move to next tick
now with tcp blocking, it could remain blocked for a very short time, or upto 2 or 3 minutes and thus timing out, once blocked nothing can be sent throught it or read from it, doing so 'locks the thread up', checking constantly if a socket is blocked is slow, and also more steps in the process that aren't needed. There is no way to 'unblock' a socket once blocked except a) closing and reconnecting (often done in browsers and what not but not in a game). b) waiting for it to become unblocked.
Suppose the host says to client 1, and 2 its time for next tick, but client 1s socket is blocked, the game then goes into a wait state for client 1s socket to unblock, or we simply contine the game and hold everything in a buffer to send to client 1 once it becomes unblocked (YUCK!).
TCP traffic for game commication layers using critical data is a BIG BIG BIG mistake that will come back and bite you in the ass.
++Cire.
Females: impossible to live with, most powerful money reducing agent known to man, 99% of the time they drive us insane; yet somehow we desire to have as many as we can.
-
- Posts: 13
- Joined: Wed Nov 21, 2007 2:38 am
- Location: America
- Contact:
its possible to just use UDP to check that the things arrive using a programed ACK back and forth rather than the built in ones from using TCP, if a computer doesn't respond in 10 seconds, its gone from the game. if the computer didnt get any of the data for 10 seconds during a huge base raid, and they come back, half of their units will be dead like magic, but so would half of the other players instantly when connection re-established.
to take it a step further, i think only chat, unit health, and game time need to be verified with an ack. if there are no Acks on those, the other computer is unlikely to have received anything else, but will eventually "catch up" once they receive the new current data.
to take it a step further, i think only chat, unit health, and game time need to be verified with an ack. if there are no Acks on those, the other computer is unlikely to have received anything else, but will eventually "catch up" once they receive the new current data.
- zuzuf
- Administrateur - Site Admin
- Posts: 3281
- Joined: Mon Oct 30, 2006 8:49 pm
- Location: Toulouse, France
- Contact:
unit direction (and body orientation) is critical if some event happens like the unit shooting, so I suggest we sync those events from the client that runs the elements that generated them.
For example:
2 clients A & B.
on A a unit is firing, A sends this information to B and also tells B that a WEAPON object has been created by A and gives all required details (weapon type, position, speed, ...). Then B receives the packet, it put the unit in firing position (but don't tell it to fire actually) and create the required WEAPON object with all the required properties.
There should also be the tick counter on packets, so when a client receives a sync packet:
1) the packet is in the future -> tells others to wait, or slow down a bit, then put this information on a stack, it'll use it when it reaches the packet tick
2) the packet is in the past -> simulate the evolution of the data received to reach current tick
For example:
2 clients A & B.
on A a unit is firing, A sends this information to B and also tells B that a WEAPON object has been created by A and gives all required details (weapon type, position, speed, ...). Then B receives the packet, it put the unit in firing position (but don't tell it to fire actually) and create the required WEAPON object with all the required properties.
There should also be the tick counter on packets, so when a client receives a sync packet:
1) the packet is in the future -> tells others to wait, or slow down a bit, then put this information on a stack, it'll use it when it reaches the packet tick
2) the packet is in the past -> simulate the evolution of the data received to reach current tick
=>;-D Penguin Powered
syncing the game state can be problematic as it could require bandwidth and thus pauses in game play while the game state is transferred.
Spring hashes the state of units and then compares hashes sent to the server, and then the server tells clients if they aren't synced.
Someone else suggested on the spring forums that instead unit orders be sent and critical events such as unit creation and death.
Spring hashes the state of units and then compares hashes sent to the server, and then the server tells clients if they aren't synced.
Someone else suggested on the spring forums that instead unit orders be sent and critical events such as unit creation and death.
- zuzuf
- Administrateur - Site Admin
- Posts: 3281
- Joined: Mon Oct 30, 2006 8:49 pm
- Location: Toulouse, France
- Contact:
The problem with syncing orders given to units is that syncing must be perfect, exactly the same on every client, because a small rounding error could make a unit chose one path over another ... and thus change the whole simulation. Since path are often refreshed, syncing them would require lots of bandwidth. Syncing only required data per unit should be ok.
let's say we have a game running 2000 units and 5 players, each player has 400 units, if you need to send position, speed and health updates for units, you'll send 400 * 7 * sizeof( float ) = 11200 bytes per synced tick if you send floats. Now there are 30 ticks per second ... so we can only sync 10 ticks per second like in TA, and syncing only events for non fully synced ticks. So you need to send 44800 (4 * 11200) bytes per tick if you sync position, speed, and health every 0.1 sec. . We don't need to send what we can compute, so let's say we can compute position and that speed won't change for half of the units (you have buildings, and units moving at full speed ...), and that speed can be computed as 1 float and a short int (speed and direction).
If you do the same for health, then you'll send less than 40 health updates per tick, and you need to send 40 * sizeof( float ) + 200 * ( sizeof( float ) + sizeof( short ) ) = 1360 bytes x 4 = 5440 bytes per tick x 10 = 54Kb/sec.
Unless we can broadcast the sync data to everyone the server will need 54Kb/sec. upload bandwidth, whereas clients will need 5Kb/s.
Of course there are data we'll need to send that are not taken into account here : weapons, events, ...
let's say we have a game running 2000 units and 5 players, each player has 400 units, if you need to send position, speed and health updates for units, you'll send 400 * 7 * sizeof( float ) = 11200 bytes per synced tick if you send floats. Now there are 30 ticks per second ... so we can only sync 10 ticks per second like in TA, and syncing only events for non fully synced ticks. So you need to send 44800 (4 * 11200) bytes per tick if you sync position, speed, and health every 0.1 sec. . We don't need to send what we can compute, so let's say we can compute position and that speed won't change for half of the units (you have buildings, and units moving at full speed ...), and that speed can be computed as 1 float and a short int (speed and direction).
If you do the same for health, then you'll send less than 40 health updates per tick, and you need to send 40 * sizeof( float ) + 200 * ( sizeof( float ) + sizeof( short ) ) = 1360 bytes x 4 = 5440 bytes per tick x 10 = 54Kb/sec.
Unless we can broadcast the sync data to everyone the server will need 54Kb/sec. upload bandwidth, whereas clients will need 5Kb/s.
Of course there are data we'll need to send that are not taken into account here : weapons, events, ...
=>;-D Penguin Powered
you dont need to send all the unit data just a hash representing the units state. This immediately pushes it down to an integer per unit. The check doesnt have to occur every frame. Then we can also just check sync every second or 2 seconds.
The idea is you only resync when the game isn't synced, and rather than continuous resyncing you just check the game states. You don't need to know the exact positions, you only need to know if they're different.
On top of that all simulation should be synced anyway so rounding errors are a bug. This is why tobi went to such effort to deal with this in spring with using streflop and messing with fpu stuff.
The idea is you only resync when the game isn't synced, and rather than continuous resyncing you just check the game states. You don't need to know the exact positions, you only need to know if they're different.
On top of that all simulation should be synced anyway so rounding errors are a bug. This is why tobi went to such effort to deal with this in spring with using streflop and messing with fpu stuff.
- zuzuf
- Administrateur - Site Admin
- Posts: 3281
- Joined: Mon Oct 30, 2006 8:49 pm
- Location: Toulouse, France
- Contact:
well the point is you don't send anything unless it's needed, so for each unit you compute a hash and put it into an integer (we won't use floating point values for the hash, only integer approx) but you do so only if you think others can simulate the data, if something changes (you give an order to one of your units) then you'll need to sync explicitly the data, otherwise you only wait for others to tell you they need to sync because their hash is different.
=>;-D Penguin Powered
Who is online
Users browsing this forum: No registered users and 20 guests