#### Archived

This topic is now archived and is closed to further replies.

# Networking Infrastructure Overview (TBS slant - 4 questions)

This topic is 5309 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Callback_PerformAction() {
thing->DoThing();
if ( network->IsOn() == true ) { // it''s a multiplayer game
network->TellEveryoneElseToDoThingToo();
}
}

is this smart? The game will be chock-full of these kinds of "if network is on, do this" kinds of statements. Now every button and slider needs to have one of these. That''s a lot! The alternative that i''m thinking about is to have all actions sent by the network only when the NEXT TURN button is pressed, then have a massive frenzy of data packet traffic. All clients upload the states of *their* units, and the server amplifies those to the other clients. Then the server would handle actually making the units interact (i.e. combat resolution). QUESTION #3: Is it better to integrate the network code into the UI and have it be realtime or should i just do one massive update at the end of turn? It seems to me the that the one-update is the cleaner way to go. The final issue is with having a client and server on the same machine, i.e. "I''m the server in a multiplayer game". The problem is that when a data packet comes in to my machine, it doesn''t know if it''s a packet meant for the server or the client. The way i have it now, I activate both client *and* server and just keep the client''s network buffer-checking loop inactive, like network->StartServer(); network->StartClient(); network->StopClientFromListening(); The other problem of course is that when a packet comes in and the server handles it, it then send the message to everyone else, including myself. This is a problem. take a chat message for example: 1) i send a chat message 2) i receive chat messsage from myself as a server 3) send that chat message to everyone else on the clients list including myself 4) repeat steps 1-3 because i keep receiving the packet as a server like an idiot, never as a client Now all code needs a special clause to it, like "Do this if i''m a server, Do something else if i''m not" QUESTION #4: Is there a smarter way to handle having a client and server on the same machine? Sorry for the extra long post. I''m sure these are pretty serious issues that we can all benefit from talking about though. Thanks for reading. I would appreciate your comments. -- leiavoia The AXIS Project http://www.project-axis.net/

##### Share on other sites
Since your doing a TBS and not a realtime game, you can spend more time on parsing data packets. Instead of going the route of a unique packet type for each data set you need to transmit, develope a more general data binding method.

For instance, a class which binds data packets into key:value pairs. The keys are used to refrence the packet data, the value holds the actualy data itself, and an additional type data to make sure you dont try to read/write the wrong types.

This would be used as such :

void send_data( Packet_Data_Stream* p_stream ){ try {  p_stream->begin_packet();  p_stream->push("Max_Turns",1);  p_stream->push("Turn_Time",5.12);  p_stream->end_packet(); } catch (Bad_Network_Stream_Exception&r) {  //handle error  }};void rcv_data( Packet_Data_Stream* p_stream ){  int   max_turns=0;  float turn_time=0.f; try {  //notice reading data from stream is order invairant,  //since it uses the key to reference the variable   p_stream->begin_packet();  p_stream->pop("Turn_Time",&turn_time);  p_stream->pop("Max_Turns",&max_turns);  p_stream->end_packet();  } catch (Bad_Network_Stream_Exception&r) {  //handle error  }};

So something like that maps packets into function instead of structs. And functions are much easier to add and maintain than the multitiude of structs, I''ve been there. There are a host of optimziation you can do, but suffice to say you can hash the key into 32 or 16 bits and have 1 byte for type data, and the data itself. So its still fairly efficient, for the flexiblity you gain.

Since the its order invariant, you can read/write in any order you wish.

To the next issue, since your making a TBS game, I suggest going the route the webservers take. Make your clients thin, build in some network UI code, run most of the simluation off the server, and serve the client pages like how a web server does.

That way you only have 1 game simulation, the one on the serve, and the clients are fully inusalted from hacking the server or the simulation.

Good Luck

-ddn

##### Share on other sites
leiavoia-

1. I''ve used a custom data packet for each type of action that can be performed. How else would you store the custom information for different types of actions/events? This process isn''t too difficult. I create a simple struct for each type of message and fill it with the needed information. So that you know what type of message is being recieved always make the first char (or first two chars if over 256 different message types) the "type" of message. When you read in the information check the first char to see what it''s value is and therefore the type of message. Then cast the message to the struct that relates to that type. It normally only takes me a couple of minutes to set up a new type of message this way.

2. I get around this by having the server do most of the processing. This stops cheaters and doesn''t have any significant performance implications. Basically all the client ever sends to the server is "can unit A do X?" and the server looks at this and if it is acceptable it sends back "Unit A can do X". As your game is Turn based it will make it a lot easier. You can send as much info as you want (within reason) and by using TCP you''ll be guaranteed that the data has arrived.

3. You should keep the network code as seperate as possible (in a seperate class if using OO). This will make changing the netcode a lot simpler as it develop''s. I use windows messaging (asynchronous) to recieve messaging and just process these incoming messages each frame. This is as real-time as you need as it occurs every frame.

4. All I did to overcome this is send messages from the server to client on one port (eg 5555) and send messages from client to server on a different port (eg 5556). This way the client listens on it''s port and the server listens on a different one. If you test with multiple clients you would then have to have each of them on their own port as well.

Hope this helps, and good luck with your development.

Doolwind

---------------------------------------------------------
Who of you by worrying can add a single hour to his life.
Matthew 6:27

##### Share on other sites
thanks for the replies. some response:

quote:
For instance, a class which binds data packets into key:value pairs. The keys are used to refrence the packet data, the value holds the actualy data itself, and an additional type data to make sure you dont try to read/write the wrong types. . . .
So something like that maps packets into function instead of structs. And functions are much easier to add and maintain than the multitiude of structs, I''ve been there. There are a host of optimziation you can do, but suffice to say you can hash the key into 32 or 16 bits and have 1 byte for type data, and the data itself. So its still fairly efficient, for the flexiblity you gain.

I''m not fully understanding what you are explaining here. My current system goes like this, for a chat message (pseudocode)

SERVERSIDE:

network->Chat("sender_name","Hello world!");

the network class then gets the function call and does this:
DataPacket_Chat* p = new DataPacket_Chat(sender, message);
p->Send(some_network_args);

the packet''s internal send routine then packs the data into the char buffer like this:
network->send(buffer, where_to);

CLIENTSIDE:

when the client gets it, it looks for the size, grabs that much info out of the network buffer, and looks at the first chunk (the type of datapacket) and reverse engineers the char-casted data it into a new object via an "auto-unpacking constructor".
// automatically grabs data from the net buffer to fill in member variables
DataPacket_Chat* p = new DataPacket_Chat(buffer_the_packet_data_is_in);
p->Handle(); // perform some action based on data

and voila! So you see, each game action needs a packet this way, otherwise the client has no concept of what it is you are trying to send and no way of knowing what it is you want done with the data.

Second issue:
From your two responses, one says put the network code in a seperate class, the other says put the network calls in the UI. You both vote for the thin client approach. There are two issues with thin clients:

1) "lazy UI". When i, say, move a slider to adjust a stat somewhere, it has to fire off a "May I?" message, the server sends back an "OK" message or a correction. That takes time over the internet. Consider something like scrolling the map screen for instance. Now some more units are visible, but the computer normally checks to see A) what units are on the map at those location, and B) if they are visible to the player. If that data is local, it''s no problem and the map would display instantly. If it''s across the Atlantic, it won''t.

2) this is also a single player game. Is it considered okay to put the single player game code on top of the network code or should it be seperate? What i mean is, if i play a single player game, should the machine still turn on a client and server and send packets to itself? or should it play "straight up" and just use the data structures in the game directly without messing with a network go-between?

The difference is that one is obviously faster. However, piggy-backing the single player game on top of the multiplayer network code would greatly simplify the UI interaction. So instead of

SomeUIFunction() {	thing->DoThing();	if ( network->IsMultiplayer() == true ) {		network->SendDoThingMessage();		}	}

i would just have this:

SomeUIFunction() {	network->SendDoThingMessage();	}

if i piggyback the network code for single player games, i get simplified coding, but less efficient interaction since every action has to go client->server->client just to get something done.

quote:
All I did to overcome this is send messages from the server to client on one port (eg 5555) and send messages from client to server on a different port (eg 5556). This way the client listens on it''s port and the server listens on a different one. If you test with multiple clients you would then have to have each of them on their own port as well.

That is brilliant. Obvious perhaps, but something i never thought of. thanks. Are you saying that every client needs to have a different port to connect to (i''m sure that''s not it), or are you saying every client on the same machine needs to have a different port? There will only be one client max on the same machine with the server. Any AI controlled players will be strictly handled by the server.

##### Share on other sites
quote:
That is brilliant. Obvious perhaps, but something i never thought of. thanks. Are you saying that every client needs to have a different port to connect to (i''m sure that''s not it), or are you saying every client on the same machine needs to have a different port? There will only be one client max on the same machine with the server. Any AI controlled players will be strictly handled by the server.

No, each client can have the same port normally, just if you want multiple clients on the one machine they will each have to listen on a different port.

quote:
What i mean is, if i play a single player game, should the machine still turn on a client and server and send packets to itself

Definately not. You should use your first piece of example code where you check "if ( network->IsMultiplayer() == true )". There is no reason to use a network messaging system (sockets) when you aren''t conneting to another computer. Just use normal function calls to achieve the same results.

quote:
Consider something like scrolling the map screen for instance

Not all actions need to be requested through the server. Something as simple as scrolling the map should be fine for the client to process, this will take some work of the server. You will have to look closely at your design as to what does or doens''t need to be requested through the server.

Doolwind

---------------------------------------------------------
Who of you by worrying can add a single hour to his life.
Matthew 6:27

##### Share on other sites

what i''m thinking is that i should keep all data up to date on all machines, but only make the turn processing on the server. This way, things like movement and combat are all reserved for the server. The client issue orders to his agents and all machines are sync''d and updated with those same orders (so they know how to display them and such), but the actual actions will be carried out on the server.

So like i may program my units to do this and that. All other machines will know what i''m going to have my units do (exploitable i know), but only the server will have them actually do it, updating all clients with the results.

sound okay or am i missing anything?

##### Share on other sites
Personally, I would get the clients sending everything to the server. Then the server will send only the information to the other clients that each client should know about. This will reduce network traffic and cut down on exploitable information. For example, fog of war, don''t send a client information about units it can''t see.

Again this comes down to personal design. The fact you''re making a turn based game will make things a lot easier.

Doolwind

---------------------------------------------------------
Who of you by worrying can add a single hour to his life.
Matthew 6:27

1. 1
2. 2
3. 3
4. 4
frob
20
5. 5
JoeJ
20

• 11
• 11
• 12
• 13
• 9
• ### Forum Statistics

• Total Topics
632214
• Total Posts
3004858

×