network module

Everything related to the code /
Tout ce qui touche au code
Post Reply
western
Posts: 27
Joined: Tue Mar 06, 2007 8:12 pm
Location: FRANCE, Toulouse

network module

Post by western » Mon Mar 26, 2007 11:25 am

Hi,
I think we should define the "use cases" (http://www.agilemodeling.com/artifacts/ ... iagram.htm) and and sequence diagram (http://www.agilemodeling.com/artifacts/ ... iagram.htm).

Please, post your opinions/inputs and I will provide a synthesis.
"same shit, different day" Stephen King's book "Dreamcatcher"

User avatar
Balthazar
Moderator
Posts: 2055
Joined: Wed Nov 01, 2006 4:31 pm
Location: Russian Federation
Contact:

Post by Balthazar » Mon Mar 26, 2007 12:07 pm

Hmm... Looks too difficult for me :? How the network support going?

western
Posts: 27
Joined: Tue Mar 06, 2007 8:12 pm
Location: FRANCE, Toulouse

Post by western » Mon Mar 26, 2007 1:14 pm

Balthazar wrote:Hmm... Looks too difficult for me :? How the network support going?
Hmmm... can you develop your question?
"same shit, different day" Stephen King's book "Dreamcatcher"

User avatar
Balthazar
Moderator
Posts: 2055
Joined: Wed Nov 01, 2006 4:31 pm
Location: Russian Federation
Contact:

Post by Balthazar » Mon Mar 26, 2007 4:09 pm

Well, programming is not my best side :)

western
Posts: 27
Joined: Tue Mar 06, 2007 8:12 pm
Location: FRANCE, Toulouse

Post by western » Mon Mar 26, 2007 7:08 pm

Balthazar wrote:Well, programming is not my best side :)
It is not necessary to be a big programmer... Are you logical? Do you play to RTS? Well, you can imagine the data exchanged between a network client and server of game. Agree? Fine, I would organize a brainstorming here and the conclusion of brainstorming will be the "use cases" dagram and sequence diagram.
"same shit, different day" Stephen King's book "Dreamcatcher"

User avatar
zuzuf
Administrateur - Site Admin
Posts: 3281
Joined: Mon Oct 30, 2006 8:49 pm
Location: Toulouse, France
Contact:

Post by zuzuf » Mon Mar 26, 2007 8:16 pm

okay, lets start:

our entities are game clients, all identical ( no server ), each client has to sync with others using the less bandwidth possible as fast as possible ( to prevent lag )
=>;-D Penguin Powered

western
Posts: 27
Joined: Tue Mar 06, 2007 8:12 pm
Location: FRANCE, Toulouse

Post by western » Tue Mar 27, 2007 4:22 pm

zuzuf wrote:okay, lets start:

our entities are game clients, all identical ( no server ), each client has to sync with others using the less bandwidth possible as fast as possible ( to prevent lag )
Hmmm... It is possible, we can implement a mesh network however this solution is totally opposite to the pursuit target: each "client" should be connected to ALL(!) other "clients", i.e each client needs two sockets (for sending and reception) for each other clients and then it will "update" the others, it should send a data (an user's/AI's action for example) to all clients, it requests CPU processing, network bandwidth and it is really possible to break the timestamps.

I think for an other solution: a privileged client (master of game) or a server and "normal" clients: all clients are connected to server, the server receives the data (the same: user's action for example) from any clients, it processes the received data and sends to clients an update of ... game engine or map or ... (to be defined!). We can use TCP for sending of client's order (the orders should be received!) and UDP (as RTP: real-time protocol) for update the clients (if the UDP packet is lost, it is not important, the server sends the packets periodically and the client which has lost the packet, will be updated with next).
And when I think to "UDP" data, I see a MPEG2 TS stream: MPEG2 is video format, there is 3 types of pictures, I-frame, P-frame and B-frame; The i-frame are JPEG picture (you can extract the frame, add a JPEG header and you obtain a jpeg file), the p- and b- are predicted and bi-predicted frame. P-frames are calculated from "previous" I-frame and B-frames are calculated from next/previous i- and p-frames and contain the "differences".

Is it possible to define an equivalent of I-frame and p-frames of game engine? If so, at beginning, client downloads from server (or game master) the "i-frame" and periodically, server sends to clients the "p-frames" of engine...


I am waiting for your inputs...

I found this page: http://www.skullbox.net/ntoplogy.php where you can find an explaination of network topologies.

Regards,
"same shit, different day" Stephen King's book "Dreamcatcher"

User avatar
zuzuf
Administrateur - Site Admin
Posts: 3281
Joined: Mon Oct 30, 2006 8:49 pm
Location: Toulouse, France
Contact:

Post by zuzuf » Tue Mar 27, 2007 5:35 pm

well by all clients, I meant all are identical, in fact it would be better to say all servers since game simulation will run on each machine. Since we will need some bandwidth I think the best solution might be to use a server based network but with the possibility to have more than just one server. For example when a "client" has a low BW connection then it will connect to only one "client" which will relay the data to network "nodes" ( clients with large bandwidth ) which will be able to send back to all low BW clients the sync data. In fact something which can adapt to connection speed and responsiveness ( so we get the best ping we can ), then if these parameters change the structure might change as well dynamically.
=>;-D Penguin Powered

User avatar
Balthazar
Moderator
Posts: 2055
Joined: Wed Nov 01, 2006 4:31 pm
Location: Russian Federation
Contact:

Post by Balthazar » Thu Mar 29, 2007 10:53 am

Maybe we should start from something more simple? Like 1 dedicated internet server and others - all clients.

User avatar
zuzuf
Administrateur - Site Admin
Posts: 3281
Joined: Mon Oct 30, 2006 8:49 pm
Location: Toulouse, France
Contact:

Post by zuzuf » Thu Mar 29, 2007 11:30 am

well this decision belongs to the network developer I think.
=>;-D Penguin Powered

User avatar
Balthazar
Moderator
Posts: 2055
Joined: Wed Nov 01, 2006 4:31 pm
Location: Russian Federation
Contact:

Post by Balthazar » Thu Mar 29, 2007 11:56 am

Yep :) Let`s hear what he`ll prefer :)

western
Posts: 27
Joined: Tue Mar 06, 2007 8:12 pm
Location: FRANCE, Toulouse

Post by western » Fri Mar 30, 2007 11:22 pm

zuzuf wrote:well by all clients, I meant all are identical, in fact it would be better to say all servers since game simulation will run on each machine. Since we will need some bandwidth I think the best solution might be to use a server based network but with the possibility to have more than just one server. For example when a "client" has a low BW connection then it will connect to only one "client" which will relay the data to network "nodes" ( clients with large bandwidth ) which will be able to send back to all low BW clients the sync data. In fact something which can adapt to connection speed and responsiveness ( so we get the best ping we can ), then if these parameters change the structure might change as well dynamically.
Wahoo! Peer-to-peer network. this demands a serious reflection.
Balthazar wrote:Maybe we should start from something more simple? Like 1 dedicated internet server and others - all clients.
I agree: we can start from a simple "server" and 5 "clients" (5 because of two things: 6 players on the same map (!) and, if our architecture is very multithreaded, 2 "network" threads by each client + 1 thread "server" + 1 thread interface between the network and engine => 12 threads!)
Then, if it is perfectly working, we can add a "farm" of servers: several servers are inter-connected, the clients connected to one of farm servers and the servers relay the data from its clients to any other connected server which "forwards" to clients.
zuzuf wrote:well this decision belongs to the network developer I think.
Balthazar wrote:Yep :) Let`s hear what he`ll prefer :)
Thank you.


Currently, I am working on network design/architecture and on sockets (under Linux, it is easy; under Windows, it is less obvious). I sent to zuzuf a pre-Alfa version of sockets for building and unit testings, using project tools (compilators, etc.).


During my reflexions, I ask myself: how can we guarantee the synchronization of game? Network communications introduce a latency in the processing and the observed behaviour should be the same for ALL clients: same causes => same effects. For example: network player named Alice attacks network player named Bob. Bob needs a time for reception and processing of Alice's data (and this time should equal to 50 or 500 milliseconds or several seconds, I do not know yet), during this period, the A's units can destroy Bob's units, buildings, etc. but Bob is not conscious of there facts.

I think, the game engine should anticipate the causes (of Alice's data) and displays (to Bob) tick+2 instead of tick+1.
What do you think? Is it possible?

Note: "same causes => same effects" or on Alice's PC and on Bob's PC, the units do the same thing: move from and to same position, attacks the same target from the same map position, etc. I think we must guarantee the identical behaviours, otherwise, the network play is impossible because two different players do not observe the same "story".

Your opinions?
"same shit, different day" Stephen King's book "Dreamcatcher"

User avatar
Balthazar
Moderator
Posts: 2055
Joined: Wed Nov 01, 2006 4:31 pm
Location: Russian Federation
Contact:

Post by Balthazar » Sat Mar 31, 2007 6:06 am

Well, it`s easy problem to solve. We use synchronisation system based on ticks. Yep, there could be latency for some time, but not too long, for example 500 miliseconds = 0,5 sec. Can you do something in 0,5 seconds that will change things? I mean if your tank being shooted by player A and 0,5 seconds passed and tank become destroyed - you can`t do anything about it. No matter will it be sync every 0,1 or 0,5 sec.

About same "story" - there should be full sync for every period (15 sec for example) when all players get`s full info about other units location.

And each tick send "current data" about unit`s movement in current tick. Maybe add info about current and previous tick - for greater stability.

Or maybe send "control sum" each 15 sec, and is control sum is correct - don`t send full info. Well, I`m not good at network at all, so feel free to discuss.

User avatar
zuzuf
Administrateur - Site Admin
Posts: 3281
Joined: Mon Oct 30, 2006 8:49 pm
Location: Toulouse, France
Contact:

Post by zuzuf » Sat Mar 31, 2007 10:05 am

when we get data for tick T we don't need those for tick T - 1. Also some actions do not need to be very synced like a unit moving from point A to point B with A which could be very far from B. What needs let's say critical synchronisation is units attacking each other because when A attacks B you could end with 3 different "stories":
1) A killed B and stay alive
2) B killed A and stay alive
3) everyone is dead

1) and 2) shouldn't be a too hard problem but 3) is:
what if A is killed by B by a shot that's fired just after B is killed on computer C1 whereas it's still alive on computer C2 ?? So I propose to take the data from the computer who owns B ( I mean where plays the player who owns B ). Then each computer runs a correct part of the simulation ( it's own part ) and the rest is synced with other players.

So if B dies on C1 whereas it belongs to C2 then C1 syncs with C2 which tells him that B is still alive. So each time a unit takes damage or is killed we should schedule a check with the owner of the unit. Also each check should be tagged with a time info ( tick number for example ) which tells when the emitter requested the info.

Of course we should sync the whole unit / weapon arrays at a speed that depends on the BW available, but we should use a priority queue for that, so critical events which must be synced are synced and others will be when possible or when needed. ( if A is moving in C2's fog of war out of radar sight there is no reason to sync it too often )
=>;-D Penguin Powered

User avatar
Cire
Moderator
Posts: 350
Joined: Tue Oct 31, 2006 5:59 pm
Location: Somewhere on Earth

Post by Cire » Mon Apr 02, 2007 1:02 am

I've been doing alot of thinking in respects to this issue and i've been reading the feedback and what not, now first:

A) You do not need 2 sockets per user per connection. The idea of having a 'send' and 'recive' socket for each user is rather overbounding and totally not in need. Instead you really only need 1 tcp socket per user that can be used for non-critcle data, such as non important game messages, chat messages and so on. Remember that tcp can become blocked and thus can acutally take time to deliver messages to the target, thus its imperative that these do not block the games natural gameplay. We should also need a udp packet for each user, the problem with UDP however is that we have no way of knowing if a packet was delievered successfully or not, so an acknowledge packet would be smart move here.

Now in respects to no server isn't truely a smart move here, the host should always be 'in control' that is in respects to who has the power of the game, if joe blow hosts a game and can't kick fred from the game then we are going to have issues. Then again if we provide other methods of games such as tourments then no one should have this power but we can probably provide these via command line args passed to ta at a later date.

Anyhow the way I see it we have 2 methods of doing things within the game, the first is:

Flag units that are 'dirty' in respects to network that others connections need to be aware of and sync them with all others, the downside to this is that if we are moving 250 units each of which need synced each tick then we are passing alot of data around each tick. The alterantive is to use some method of 'orginized' fpu math, solving this means that we only need to pass orders and sinc fpu math would be synced then we can sync units perioidicly and reduce network lag at least 10 to 20 fold.

So the problem is how to do fpu math in a synced sorta fasion. First, why do we need to do this, well Floating point math can vary greatly from one cpu to another. Yes we could easilly figure out at lauch time doing some 'test calculations' to find out how close each machine is to each other in respects to mathimitical equations but we are still going to run into issues in having 1 or 2 or 3 comps handle all calculations for not only them but others, which also isn't a good idea.

Now yes there are some math libs out there that would give us much better results but switching to these would require alot of recoding and one miss use may result in throwing the whole game outa sync.

So the question is how do we sync units without traversing tons of packets foreach user to each user each tick. Well the answer is pretty much staring us right in the face:

To begin we establish a tcp/udp connection to each and every user in the game, at launch time we run through a serious of tests to check who has the fastest connection as well as the fastest cpu, we select this user as the 'server', shoulc the server drop we simply reitterate other users and swap the new user as the selected server. Now heres where it gets interesting the server isn't really a server in respects to serving the game but rather is the user who is really managing the game. What i mean by that is...

He is the only true player, the other players are networked players issuing orders to him he in turn does all the dirty work, it is him that syncs other users with dirty units, but he don't need to do all the dirty work for example....
tick occurs:
A updates B
--------------
B updates D
A updates C

If there was more players in the game suppose 16
1 updates 2
--------------
2 updates 3
1 updates 4
----------------
4 updates 5
1 updates 6
2 updates 7
3 updates 8
-----------------
8 updates 9
7 updates 10
6 updates 11
5 updates 12
4 updates 13
3 updates 14
2 updates 15
1 updates 16
----------------------------

In total for a complete unit update 4 sends each client can be set to 'pass on' data to another client reducing network latency.

Now for packet conection I suggest we use a superclass packting system. starting with a simple bass class of a packet type (enum based ) short int maybe, lenght of data of packet, and unit8 data.

From that base class we can derrive superclasses that can take the base class as an argument and use the data how its meant to be used. If properly implemented a unit should be able to construct a packet push it on the the send que and also recive the packet and update its data with the new packet info. Threading however might be an issue if its not carefully handled.


In essence what i mean here is that when a client says move my commander to location a,b,c hes not doing any of that hes sending the order to the current selected server, that server then flags that unit as dirty and then does calcuations for accerlation, turn rates ect when network data is sent out it sees that as a dirty unit and its thus updated at all other clients in respects to a shared distrubted data system.

Thoughts?

++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.

User avatar
Balthazar
Moderator
Posts: 2055
Joined: Wed Nov 01, 2006 4:31 pm
Location: Russian Federation
Contact:

Post by Balthazar » Mon Apr 02, 2007 7:01 am

Well, sounds good, but I don`t fully understand. Does server makes all the calculaton for other players, or only the "dirty" ones?

Is server hold "correct" units locations based on it`s own calculation and clients orders data and compare it with other`s clients results for not "dirty" units?

P.S. Wellcome back Cire :)

User avatar
zuzuf
Administrateur - Site Admin
Posts: 3281
Joined: Mon Oct 30, 2006 8:49 pm
Location: Toulouse, France
Contact:

Post by zuzuf » Mon Apr 02, 2007 11:37 am

well if we use a server to do all the "official" calculations this server will need lots of up BW since he will send most of the units array. ( 2000 units per player at 24o per unit ( I dream :roll: ) = 48ko :cry: ).

About FPU syncing just one thing :
it's mainly about rounding errors, so on a 32bits float it's negligible for a few sec. ( we don't try to compute PI digits here, we don't need extreme precision ). And also are we going to use 32bits for a float ?? ( there are many values that aren't going to be used for some vectors ).
=>;-D Penguin Powered

User avatar
EvanR
Posts: 46
Joined: Tue Oct 31, 2006 6:24 pm
Location: United States
Contact:

Post by EvanR » Tue Apr 03, 2007 12:31 am

Hey guys. I read some threads to try and catch up on ta3d. Welcome to western the new programmer! Zuzuf recruited me as 'the network developer' since I expressed an interest in making sure ta3d had IPv6 support. Obviously I have been too busy with two jobs and college (its my last semester and I have lots of classes) to work extensively on it.

Last time I worked on it, there was all the pieces for a working net game except for some decision-making on who to send whom what updates. As far as I knew the model was that all clients calculate unit physics and send orders for their units to all other clients to use in their version of the world. Periodic distributed updates to position would be made to account for accumulated errors. This scheme has a cheating problem associated with it, but who cares right? :) This policy is the part that is currently missing from the code, so my plan is to put it there, and then if you all think there is a better way you can rip it out later.

This week I am on vacation and I and planning on implementing some of Cire's suggestions like making the net code more c++-like. I can only test the network files on linux, as I do not have visual c++ (dev c++ the free IDE will not understand our windows code).

I would definitely appreciate some help and suggestions from western and others. Can someone please update me on the progress?

User avatar
Cire
Moderator
Posts: 350
Joined: Tue Oct 31, 2006 5:59 pm
Location: Somewhere on Earth

Post by Cire » Tue Apr 03, 2007 5:03 am

Well since FPU math shouln't be an issue I still don't see the need to distrubute tons of unit updates per tick. Instead why don't we still send orders to clients, ie using these units move to this location, or build this at this location and so on.

Since accerlation, build time, ect should be the same then if i order a unit on my machine to move to location x,y and that same unit on your machine is at location a,b as well as mine and acceleration and ticks are occuring at 'synced' intervals then logically they should arrive at the same time. The only issues I see is random targeting and so on, ie on my machine they may randomly target unit b, where on his machine they may randomly target unit c, but we could do a case lookup for random targets or specifically let each client simply send its fire synquence order for each unit, but again I don't think thats a wize move either.

The point is if we need to update 2400 units accross say 8 players every tick we are going to have a hell of a lagging game. This is one are we should not jump into quickly, and really need to think through carefully.

++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.

User avatar
zuzuf
Administrateur - Site Admin
Posts: 3281
Joined: Mon Oct 30, 2006 8:49 pm
Location: Toulouse, France
Contact:

Post by zuzuf » Tue Apr 03, 2007 10:50 am

we don't need to sync every unit each tick. FPU precision isn't that critical but it remains a problem for long game synchronisation. As far as randomness is concerned we could use an alternative random numbre generator (like the one we already have) that stay synced with other clients to prevent some events to get a client out of sync. It will still appear "random" whereas it's not because it will be predictable.
=>;-D Penguin Powered

western
Posts: 27
Joined: Tue Mar 06, 2007 8:12 pm
Location: FRANCE, Toulouse

Post by western » Tue Apr 03, 2007 1:48 pm

EvanR wrote:Hey guys. I read some threads to try and catch up on ta3d. Welcome to western the new programmer! Zuzuf recruited me as 'the network developer' since I expressed an interest in making sure ta3d had IPv6 support. Obviously I have been too busy with two jobs and college (its my last semester and I have lots of classes) to work extensively on it.

Last time I worked on it, there was all the pieces for a working net game except for some decision-making on who to send whom what updates. As far as I knew the model was that all clients calculate unit physics and send orders for their units to all other clients to use in their version of the world. Periodic distributed updates to position would be made to account for accumulated errors. This scheme has a cheating problem associated with it, but who cares right? :) This policy is the part that is currently missing from the code, so my plan is to put it there, and then if you all think there is a better way you can rip it out later.

This week I am on vacation and I and planning on implementing some of Cire's suggestions like making the net code more c++-like. I can only test the network files on linux, as I do not have visual c++ (dev c++ the free IDE will not understand our windows code).

I would definitely appreciate some help and suggestions from western and others. Can someone please update me on the progress?
I have modified your SocketClass.cpp and sent the new files to zuzuf for testing. On my environment Linux and Windows (I use mingw), it works but valgrind indicates a memory problem. I did not fix yet.

I want to create a valid use case diagram and a sequence diagram (I think that UML is a good pratice when a project is considerable and when several developers contribute).
For this, we need to define the exchanged data following the requirements (low bandwidth, etc.).
And the first problem is the "random" target and the second is data quantity.
It is possible to solve the first problem if instead of random target, client sends "attack this target": when the "humain" player orders the unit "go&attack", the unit goes and choices its targets randomly and when the unit choose the target, the network client sends to remote client/server the equivalent of "go&attack this/these target(s)".
Zuzuf, when the unit selects its target?

For second problem, we need to find a "clever way"
"same shit, different day" Stephen King's book "Dreamcatcher"

User avatar
EvanR
Posts: 46
Joined: Tue Oct 31, 2006 6:24 pm
Location: United States
Contact:

Post by EvanR » Tue Apr 03, 2007 4:42 pm

Western can you please send me a copy of the changes you have made? I do not want to start messing with stuff at the same place at the same time as you. If there is a memory problem I think it is likely from the queue structure I wrote. It is a complicated C structure using malloc and free. One of the things I was going to do is throw out the superqueue and just use one of the c++ stl container objects.

I did not mean to imply doing updates every tick, the position updates can be made once every few minutes. Since there will be a lot of units perhaps the updates can be distributed in time so we dont have one huge update. Without floating point errors the units will still be out of sync since there will be short time delays associated with sending orders.

I tried to compile my stuff with mingw but the windows header files that came with my distro lacked necessary windows ipv6 stuff. Perhaps that has changed?

User avatar
zuzuf
Administrateur - Site Admin
Posts: 3281
Joined: Mon Oct 30, 2006 8:49 pm
Location: Toulouse, France
Contact:

Post by zuzuf » Tue Apr 03, 2007 5:11 pm

Units choose a target when they have no direct order not to do it. So when they patrol or when they aren't doing anything. That decision is taken in the UNIT::move(...) function in UnitEngine.cpp/.h.

Because of transmission delays I think using full 32bits floating point variables for data like unit's position/speed is useless. TA uses a 32bits int to store coordinates on the map within scripts. So for land units 32bits should be enough to store its position, plus 32bits for speed ( yes it's 2D planar speed ) and one more coordinate for planes.

Since the game simulation will run everywhere we need to sync events. I think we should use a priority queue to send critical events before other low priority events. Such events would be events like creating/destroying an object ( unit or weapon ) which cannot be skipped.

Since our network developpers are using mingw32 I am going to get back mingw32 compatibility.
=>;-D Penguin Powered

western
Posts: 27
Joined: Tue Mar 06, 2007 8:12 pm
Location: FRANCE, Toulouse

Post by western » Tue Apr 03, 2007 7:21 pm

Zuzuf, please, can you post somewhere the latest archive which I sent you as EvanR requested?


EvanR, the sockets code is pre-Alfa but it works... I "removed" your loop which sorts the addresses and I do not test all functions, for example, Accept (sock, timeout). Also, I tried to add the comments for the classes, the functions, etc. or an explanation of functioning. Please, can you complete? For building on Wndows using mingw, I added -lws2_32 and -D_WIN32_WINNT=0x0501 to build command.
"same shit, different day" Stephen King's book "Dreamcatcher"

User avatar
zuzuf
Administrateur - Site Admin
Posts: 3281
Joined: Mon Oct 30, 2006 8:49 pm
Location: Toulouse, France
Contact:

Post by zuzuf » Tue Apr 03, 2007 7:59 pm

=>;-D Penguin Powered

User avatar
EvanR
Posts: 46
Joined: Tue Oct 31, 2006 6:24 pm
Location: United States
Contact:

Post by EvanR » Tue Apr 03, 2007 8:17 pm

Western: I looked through it, nice job making it more 'object oriented'. The reordering of lookup addresses to put ipv6 first was just a sort of 'network activism', but its fine that you removed it. Do you have the ability to upload to the CVS? It would be nice if we could collaborate that way. What are your plans for the rest of the network code besides socket class? Just wondering.

User avatar
zuzuf
Administrateur - Site Admin
Posts: 3281
Joined: Mon Oct 30, 2006 8:49 pm
Location: Toulouse, France
Contact:

Post by zuzuf » Tue Apr 03, 2007 8:39 pm

as far as CVS is concerned if you need it then create a new dir in the CVS root ( network module ? ) because we currently have some problems with it.
=>;-D Penguin Powered

western
Posts: 27
Joined: Tue Mar 06, 2007 8:12 pm
Location: FRANCE, Toulouse

Post by western » Wed Apr 04, 2007 7:50 am

EvanR wrote:Western: I looked through it, nice job making it more 'object oriented'. The reordering of lookup addresses to put ipv6 first was just a sort of 'network activism', but its fine that you removed it. Do you have the ability to upload to the CVS? It would be nice if we could collaborate that way. What are your plans for the rest of the network code besides socket class? Just wondering.
Well, my "planning" is
- fully functional, commented and very fast sockets on Windows, Linux (and other OS if possible): sending and receiving of small data and large "files" (for example, transfer of hpi/udo files, etc.) using TCP and UDP on IPv4 and IPv6 (currently, I am unable to test IPv6). We need to test the server and client code using valgrind for memory profilling and gprof for performance profilling
- definition of several UML diagrams (use cases diagram, sequence diagram, etc.)
- definition of exchanged data and "network protocol" (we can compress the data)
- definition and development of interface(s) between game engine and network
- developement of module (based on sockets and threads)

Your inputs?
"same shit, different day" Stephen King's book "Dreamcatcher"

User avatar
EvanR
Posts: 46
Joined: Tue Oct 31, 2006 6:24 pm
Location: United States
Contact:

Post by EvanR » Thu Apr 05, 2007 9:36 pm

About compression, the overwhelming majority of data sent will be in the form of raw pointing point numbers. Since this data is like random there is no way to compress it significantly. Compression for chat would conceivably reduce throughput greatly but chat doesn't happen very often compared to unit syncs. Compressing and decompressing the raw float streams would also add to time and computation requirements, so it is probably not a good idea.

If you look at the TA3DSock you'll see I conceived of four 'kinds' of messages and methods for sending and receiving them. The messages appear as C structs (with fields like 'x position' 'y position' etc) to the application but maybe this could be better. I assume the raw hard numbers (not chat) will be sent with the socket objects UDP feature. I am thinking that since one unit sync or one order will have a pretty small size (less than 20 bytes) there will be no packet fragmentation problems. The characteristic udp feature where packets might not arrive at all is not a problem for unit syncs but it is for orders. Orders should be sent on tcp for reliability (i think). Conclusion: minimal fiddling with udp is necessary for our purposes.

Needless to say, I probably won't be able to work on this anymore pretty soon. Its good to know someone is there to clean up after me!

western
Posts: 27
Joined: Tue Mar 06, 2007 8:12 pm
Location: FRANCE, Toulouse

Post by western » Fri Apr 06, 2007 7:49 am

EvanR wrote:About compression, the overwhelming majority of data sent will be in the form of raw pointing point numbers. Since this data is like random there is no way to compress it significantly. Compression for chat would conceivably reduce throughput greatly but chat doesn't happen very often compared to unit syncs. Compressing and decompressing the raw float streams would also add to time and computation requirements, so it is probably not a good idea.

If you look at the TA3DSock you'll see I conceived of four 'kinds' of messages and methods for sending and receiving them. The messages appear as C structs (with fields like 'x position' 'y position' etc) to the application but maybe this could be better. I assume the raw hard numbers (not chat) will be sent with the socket objects UDP feature. I am thinking that since one unit sync or one order will have a pretty small size (less than 20 bytes) there will be no packet fragmentation problems. The characteristic udp feature where packets might not arrive at all is not a problem for unit syncs but it is for orders. Orders should be sent on tcp for reliability (i think). Conclusion: minimal fiddling with udp is necessary for our purposes.

Needless to say, I probably won't be able to work on this anymore pretty soon. Its good to know someone is there to clean up after me!
For network architecture, I think like you:
From server to clients communication: UDP
From clients to server: TCP

I have spoken compression because it is a possibility, the data format and protocol are not yet defined, the volume of data to sync is not defined. Large number of units creates an important volume of data to sync, and if the units are neighbour, the data can be similar then the compression is possible. I agree that compression requests CPU and other resources however if server sends "tick+1" data (I continue to think that it is a good idea to sync the already computed data, thus, we remove the random, the network latency should be ignored), in clients scope, we will have the time to uncompress
"same shit, different day" Stephen King's book "Dreamcatcher"

User avatar
zuzuf
Administrateur - Site Admin
Posts: 3281
Joined: Mon Oct 30, 2006 8:49 pm
Location: Toulouse, France
Contact:

Post by zuzuf » Fri Apr 06, 2007 11:16 am

we will never have to process a 1Mb/sec. stream, so compression is possible, especially for low BW connections. a LZW algorithm (optimized) can compress quickly a huge chunk of data, and it's faster to uncompress. If compression is a problem for you, I can deal with it.
=>;-D Penguin Powered

western
Posts: 27
Joined: Tue Mar 06, 2007 8:12 pm
Location: FRANCE, Toulouse

Post by western » Fri Apr 06, 2007 1:41 pm

zuzuf wrote:we will never have to process a 1Mb/sec. stream, so compression is possible, especially for low BW connections. a LZW algorithm (optimized) can compress quickly a huge chunk of data, and it's faster to uncompress. If compression is a problem for you, I can deal with it.
The compression is not a problem but the compression is really effective on similar "patterns" in data. In our case, the data is not yet defined, we cannot conclude if the compression should be effective or non, it is just a possibility.
"same shit, different day" Stephen King's book "Dreamcatcher"

User avatar
zuzuf
Administrateur - Site Admin
Posts: 3281
Joined: Mon Oct 30, 2006 8:49 pm
Location: Toulouse, France
Contact:

Post by zuzuf » Fri Apr 06, 2007 7:34 pm

actually a compression algorithm is effective on data type it's made for. You do not really need patterns to repeat for Huffman algorithm to be efficient. Or even if the data doesn't seem compressible you can make a reversible transformation to compress it better (cf Burrow Wheeler transform).
But yes there are limits to these algorithms. But we still have to define what data to sent over the network.
=>;-D Penguin Powered

User avatar
Cire
Moderator
Posts: 350
Joined: Tue Oct 31, 2006 5:59 pm
Location: Somewhere on Earth

Post by Cire » Sat Apr 07, 2007 1:07 pm

I suggest for each unit having a NetworkSync flag, and adding a Function for collecting a socketdata from that unit which returns say a void.

Next you will need a set of global flags that the engine will apply to the unit as it becomes 'dirty', Reset it each time it sends data to NETWORK_UNIT_NOT_DIRTY which would be defined to '0', if the unit changes its speed that flag is applied ie NETWORK_UNIT_SPEED_DIRTY, which would be defined as '2', would also need flags for UNIT_FACING_DIRTY, LOCATION_DIRTY, HEATLH_DIRTY, and others as needed such as the 'open status or weapon facting direction whatever else is needed.

Now the key is a class that each unit would generate based on its data that changed, some units may return 'null' which means nothing has changed, the class might simply contain a 'buffer' of unit8 data, which the unit would fill out, in essence what you are doing here is seralizing data only placing the data for each unit that requires updating into a class. The units seralizing function would return a class or null.

Next in the core engine all you would need to do is.....
for [each unit that I own] in all units
packets += unit->GetSeralizingDataClass();
next

Packets = filter_out_nulls;
Packets.SortByCriticle();
DataSize = Packets -> GetDAtaSize();

unit8 SendBuffer[ DataSize ];
foreach Packet in Packets
Packet->InsertIntoBuffer( offset, SendBuffer );
offset += Packet->DataSize();
next

CompressData( SendBuffer );
sockets->SendUDPData( SEndBuffer );

cleanup packets;

That should give you a quick and dirty means of only updating units which are dirty, sorting data by criticle, compressing data and generating data based only on whats dirty in each unit rather then a complete resync each time. I realize that its hardly complete C++ but its just a quick example to show you how I would attain the results. Seralzing will make things alot easier, and you could simply push it into a buffer realocating the size of the buffer as needed but I belive that pushing it into a 'packet' class will allow you further options down the road.

Furthermore remember that UDP is not dependable, so you might want to keep track of how much you sent to each socket and have that target generating a 'acknowledge packet', if it don't recive one over so many updates it may wish to 'resend', and if you 'id your packets then 2 sends of the same packet id would simply be 'ignored'.

Anyhow hope I'am making since here, what your going to find is that a good 90% of the time you are simply updating location, facing and perhaps weapon facing directions. This should cut down on the amount of data you send drastically.

++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.

western
Posts: 27
Joined: Tue Mar 06, 2007 8:12 pm
Location: FRANCE, Toulouse

Post by western » Thu Dec 13, 2007 8:27 pm

up my previous topic about network module
"same shit, different day" Stephen King's book "Dreamcatcher"

User avatar
zuzuf
Administrateur - Site Admin
Posts: 3281
Joined: Mon Oct 30, 2006 8:49 pm
Location: Toulouse, France
Contact:

Post by zuzuf » Thu Dec 13, 2007 8:43 pm

Cire -> That's a good idea, all linear complexity, I like it :D .

The packet ID is good to keep sync easily. We can also avoid sending some packets about things that can be computed easily: ie when you have speed and previous position, then you have new position unless speed has changed (this will always be computed, so even if you don't get a sync packet on that you'll have smooth animation). Every time a unit is hit (or its position takes an important parts in some critical event) its position, speed, orientation must be synced to avoid rounding errors.
=>;-D Penguin Powered

Post Reply

Who is online

Users browsing this forum: No registered users and 31 guests