Hi there,
I've added networking to my game engine and I can make a host & client between 2 laptops via hamachi ( school told me to use a vpn because of the school servers that blocks almost everything ).
So I can send data of both 'enemies' to each player ( x-position, y-position, width, height ) and then I can check for collision. But this is only for 1 little cube.
What should I do if I need to send 20 different objects with their own information ( armour, defence, attack, width, height, position, etc ) to both players? I'm using winsock for my connection by the way.
I would like to use XML to set the general informations( armour, defence, ... ) of all units and buildings. So suppose both players got that same XML file. Then I should just send the type ( which unit/building it is ) and the position right? Because I can receive all general information of that XML file. Is this a good/usual way to do this?
In big games they work with databases but I haven't practiced with that yet. The disadvantage of using 2 XML files for host & client is that both players can change some values and 'cheat'. But this is only for school so I don't really care about making it totally safe for 'not cheating'.
So the main questions are: How should I send all data? Should I use XML or not? Is there any disadvantage of using XML ( except it's not cheat safe )? Is there a better way ( except databases, I'm don't have a lot of experience with this )
B. Jonathan
Sending data through the internet
It's not XML that's fundamentally vulnerable to cheating, it's that you seem to be using an architecture where both laptops maintain their own gamestate - so which one is more valid than the other? Neither which means there is no protection against cheating regardless of how you send data between two laptops. Usually you use a server-client model where one laptop maintains the trusted gamestate and handles all the requests, to prevent or at least make cheating very difficult. (so for instance if in some hypothetical game a client wanted to move from position 0 to position 100 in a single step, but is meant to go through each step one by one, the server will receive the 0->100 request, look at it and say "uhoh, no way" and discard it - and optionally kicking the client for cheating).
Sending an XML file over the internet is certainly not the best way you could do it, simply because XML files have very high redundancy (so it's a waste of bandwidth to use them over the internet). The usual way is to agree on a protocol with as little redundant information as possible, and send information that way. For instance you'd have one "packet" (identified by a particular code) which would contain the information for an object, in a binary form, and since both clients know what the code represents and how to interpret what follows it they can read it without any issues. It's really just a form of "XML file" but better-suited to internet transmission.
So to summarise, the concept is correct (apart from the architecture which is a bit off), but XML files are not well-suited for online realtime communication. Although - if you are just using the two laptops on LAN you may not notice the issues because it ultimately *works* and LAN networks are so fast that there is no practical difference, but when you'll be wanting to make two computers from all over the world communicate XML isn't going to cut it.
Sending an XML file over the internet is certainly not the best way you could do it, simply because XML files have very high redundancy (so it's a waste of bandwidth to use them over the internet). The usual way is to agree on a protocol with as little redundant information as possible, and send information that way. For instance you'd have one "packet" (identified by a particular code) which would contain the information for an object, in a binary form, and since both clients know what the code represents and how to interpret what follows it they can read it without any issues. It's really just a form of "XML file" but better-suited to internet transmission.
So to summarise, the concept is correct (apart from the architecture which is a bit off), but XML files are not well-suited for online realtime communication. Although - if you are just using the two laptops on LAN you may not notice the issues because it ultimately *works* and LAN networks are so fast that there is no practical difference, but when you'll be wanting to make two computers from all over the world communicate XML isn't going to cut it.
I would like to use XML to set the general informations( armour, defence, ... ) of all units and buildings. So suppose both players got that same XML file. [/quote]
I meant that both players already will have the XML file before the game starts. I'm writing my game and XML on my laptop and when I want to test it I send all stuff to a friend of my ( that will play as client ).
Suppose I got this kind of information of every unit:
( this is pseudo code )
< unit; type = orc; damage = 17; armour = 50; health = 150; width = 40; height = 50; etc.. > // width and height is the size of that unit in the spritesheet.
So if I send the position & type of my orc to the client he knows where my orc is on the field + he can look into the XML file to know what the size is of that unit ( for collision detection ).
But is this a normal way of doing? I'm not worried about cheating because I'm not using this commercial. My friend knows what to do ( he only needs to open the .exe file and test it )
So I'm not sending any XML files.. I just send the position + type of my units. But I don't know how I can send and receive a lot of information on a fast way...
Can I have some pseudo code of how I should write everything so let it work smoothly?
I need so send a lot of information ( example= 30units and 5buildings )
Then I need to receive a lot of information too ( example = 20units and 6 buildings )
How can I do this? And how should I hold all information? (vector, list, etc)?
Well realistically the amount of information you can send in a given time is limited. The problem is that you want pseudocode for network communication, but it really is impossible to write pseudo-netcode. It depends on so much factors, i.e. how often do you need to send that information, how much information, and how fast must it make it to its destination, the location of both laptops, etc...
I think you are confusing yourself a bit - if you are not sending any XML file, but merely reading and writing from/into it, then the fact that you use an XML file is irrelevant to the concern at hand, i.e. networking.
You mentioned "But I don't know how I can send and receive a lot of information on a fast way...", what do you mean by fast?
Fast networking can't be solved by implementing some algorithm, it's mostly practical. For instance there are two (in the broadest sense) ways of sending information on the internet, via the TCP (Transfer Control Protocol) and UDP (User Datagram Protocol) respectively. The TCP guarantees that any information you send over the internet will reach its destination, and guarantees it will arrive in the order it was sent, however it says nothing about speed. On the other hand, UDP doesn't make any promises about whether what you send will reach its destination, the order in which it will arrive, and I'm not even sure it guarantees integrity. It sounds like no one would use UDP over TCP, but there is one major difference - if you send something via UDP, and if it actually arrives, it arrives fast, because the protocol doesn't need to account for anything like order of arrival, etc... so if you don't care about those it is better to use UDP.
What and how you need to code completely depends on your needs.
What is your problem i.e. what issues do you encounter with your current model? Latency in the transfer of data? Inconsistent transfer speed?
I think you are confusing yourself a bit - if you are not sending any XML file, but merely reading and writing from/into it, then the fact that you use an XML file is irrelevant to the concern at hand, i.e. networking.
You mentioned "But I don't know how I can send and receive a lot of information on a fast way...", what do you mean by fast?
Fast networking can't be solved by implementing some algorithm, it's mostly practical. For instance there are two (in the broadest sense) ways of sending information on the internet, via the TCP (Transfer Control Protocol) and UDP (User Datagram Protocol) respectively. The TCP guarantees that any information you send over the internet will reach its destination, and guarantees it will arrive in the order it was sent, however it says nothing about speed. On the other hand, UDP doesn't make any promises about whether what you send will reach its destination, the order in which it will arrive, and I'm not even sure it guarantees integrity. It sounds like no one would use UDP over TCP, but there is one major difference - if you send something via UDP, and if it actually arrives, it arrives fast, because the protocol doesn't need to account for anything like order of arrival, etc... so if you don't care about those it is better to use UDP.
What and how you need to code completely depends on your needs.
What is your problem i.e. what issues do you encounter with your current model? Latency in the transfer of data? Inconsistent transfer speed?
Thanks for the quick reply.
I don't know how "fast" the transfer speed of a network is.. I just don't want any lag that's all. I'm using TCP because I need a safe connection. My data need to be received in a strict order.
And because I don't want any lag at all I started with multithreading. I'm using the main thread for the whole game, 1 thread for just the network and 1 thread to do all the pathfinding.
About the code, I don't really know how I should 'hold' all information. Should I hold all informations in a list, vector, deque, map, etc?
And how should I send it, should I send all information in 1 long string?
I want to play in a revealed map. So I need to see everything on the field including the enemy, where his buildings are, where his units are, etc. But if he got 100+ units and every unit has 3 variables ( type, Xpos, Ypos).. Should I send this all in 1 string?
Should I write it like that?
I never worked with a network before so I don't know if this is the way of doing..
B. Jonathan
I don't know how "fast" the transfer speed of a network is.. I just don't want any lag that's all. I'm using TCP because I need a safe connection. My data need to be received in a strict order.
And because I don't want any lag at all I started with multithreading. I'm using the main thread for the whole game, 1 thread for just the network and 1 thread to do all the pathfinding.
About the code, I don't really know how I should 'hold' all information. Should I hold all informations in a list, vector, deque, map, etc?
And how should I send it, should I send all information in 1 long string?
I want to play in a revealed map. So I need to see everything on the field including the enemy, where his buildings are, where his units are, etc. But if he got 100+ units and every unit has 3 variables ( type, Xpos, Ypos).. Should I send this all in 1 string?
string sendString = "orc1 10 50 orc2 170 40 mage1 340 30 academy1 120 50 etc etc etc";
Should I write it like that?
I never worked with a network before so I don't know if this is the way of doing..
B. Jonathan
It doesn't matter if you send it all as one string or not because of the way TCP works. In TCP, there is no beginning or end to a message or string. It's just a continual flow of data, with the beginning at the time you make a connection and the end at the time the two computers disconnect.
You have to come up with a way to differentiate between packets of data in your program, and then send the relevant information in packets. One common method is to say at the beginning of a packet how long the packet is, and then read from the stream until the specified number of bytes are read, and then process the packet. How you format the packet and what information you put in it is entirely up to you. Whether you break information up into lots of small packets or just a couple larger packets, is entirely up to you. The network doesn't care too much, because, like I said, TCP is just a continual stream of data, so it doesn't care/know if you're sending lots of small packets or one larger packet.
You have to come up with a way to differentiate between packets of data in your program, and then send the relevant information in packets. One common method is to say at the beginning of a packet how long the packet is, and then read from the stream until the specified number of bytes are read, and then process the packet. How you format the packet and what information you put in it is entirely up to you. Whether you break information up into lots of small packets or just a couple larger packets, is entirely up to you. The network doesn't care too much, because, like I said, TCP is just a continual stream of data, so it doesn't care/know if you're sending lots of small packets or one larger packet.
I don't know how "fast" the transfer speed of a network is.. I just don't want any lag that's all. I'm using TCP because I need a safe connection. My data need to be received in a strict order.
And because I don't want any lag at all I started with multithreading. I'm using the main thread for the whole game, 1 thread for just the network and 1 thread to do all the pathfinding.[/quote]
Firstly lag *will* exist, there will always be latency over the internet, and if you want the least lag possible you'll usually need to do some compromises and use UDP if it is compatible with your design needs. But for your case TCP will be just fine, because as you said it's just a small school project, and you can always improve it later on, and TCP is easier to start with and work with in general. As Cornstalks says TCP considers anything you send as a stream of data, and this also raises the issue of data delimitation, i.e. if you send over TCP the strings "hello" and "world", then after a given time the receiver might receive "hello" then "world", or it might receive "helloworld" directly, or might even receive "hel" then "lowo" then finally "rld", depending on how the data's been travelling over the network (although it will always be in the right order) - it depends on how much of the "stream" reached its destination at the time the receiver decides to check if anything has arrived.
You could use a string as you suggested, but you would need to send a number right before sending the string, that describes the length of the string, to be able to know when the string ends (since it's possible you'll only receive a bit of the string, then the rest of the string a few milliseconds later). Or you could also work with null-terminated strings - add a null (#0) character at the end of any string, so that when this character is received the receiver knows the string has been received completely and can read it.
Usually you don't send strings, but instead convert the data you need to send into binary structures, i.e. in your case the "type" could be represented by a number, with an agreed upon convention (i.e. 0 = orc, 1 = mage, 2 = academy), then the x-position is represented by another number, etc... while sending the total size of the structure before sending the structure itself. It's more TCP-friendly and also much smaller (in size) that the equivalent string representation. It's also easier to read, because you literally only have to read from the binary structure, whereas with a string you'd need to parse it, then convert the string representations of your data into binary form (which is what you use for your logic, aka integers for position, etc...).
The best way to get things quickly sent over the internet is to (1) send as little as possible and (2) send as much as possible.
Wait, what?
(1) is easy to understand. The fastest bytes to send are the ones already on the other computer. Your XML file for storing unit info is a good example. You don't need to send the armor and size and attack value every time because it never changes. Going further, why send the data for Orc #45067 if it never moves and doesn't get hit? Nothing's changed, so why update it? And you don't have to update every time the unit moves a pixel either. Just send "He's going at this speed in this direction" and don't send another packet unless that changes. Another way to reduce sizes is to not send bytes you don't really need. If you can't have 4 billion objects in your game, why send all 4 bytes of the object ID? Do you really need to send that number as a float instead of a short? Does the other computer really need to know which exact frame of animation the Orc is on, if all the animation is for is looks? If each unit can only face 16 directions, you can send that in half a byte rather than 4. Pack a few flags in the other half and the savings add up.
(2) means to try and send a bunch of updates in one big go. Packets do have their own overhead (mainly error checking and where it's headed to/coming from) that has to be sent over the wire. If each packet has it's own overhead of 42 bytes (number made up) and you need to send 500 unit updates, then sending each unit individually would ~20.5 Kilobytes of unavoidable overhead. That's not even counting the actual unit data. Instead, send a single large packet (or a couple of medium-sized packets) that says at the beginning "I have 500 unit updates" and only has an unavoidable overhead of 42 bytes (still made up number). The driver does try to do this for you, but often times it gets in the way by not sending the data when you expect it to ("But I still need 3 more bytes to fill my buffer! I'll send the rest of this when you give me those last 3 bytes."), which is not good when you're expecting low latency. Most people end up turning that feature off for their socket and manually combine packets to give them the best of both worlds.
Edit: I just looked up the actual overhead for a single network packet, and it ends up being ~82 bytes. So for my 500 unit example, the overhead just for the packet headers is ~40 Kilobytes. Ethernet has a packet size limit of 1500 bytes, which includes the IPv4 and TCP headers of ~40 bytes, so 1460 bytes per packet is about the size you'll be shooting for to get optimal data rates. Assuming 16 bytes per unit update you can fit around 90 units in a single packet, plus a little per-packet bookkeeping (timestamp and error checking if you go UDP, unit update count, etc.). My numbers were obtained here in case anyone wants to check facts.
Wait, what?
(1) is easy to understand. The fastest bytes to send are the ones already on the other computer. Your XML file for storing unit info is a good example. You don't need to send the armor and size and attack value every time because it never changes. Going further, why send the data for Orc #45067 if it never moves and doesn't get hit? Nothing's changed, so why update it? And you don't have to update every time the unit moves a pixel either. Just send "He's going at this speed in this direction" and don't send another packet unless that changes. Another way to reduce sizes is to not send bytes you don't really need. If you can't have 4 billion objects in your game, why send all 4 bytes of the object ID? Do you really need to send that number as a float instead of a short? Does the other computer really need to know which exact frame of animation the Orc is on, if all the animation is for is looks? If each unit can only face 16 directions, you can send that in half a byte rather than 4. Pack a few flags in the other half and the savings add up.
(2) means to try and send a bunch of updates in one big go. Packets do have their own overhead (mainly error checking and where it's headed to/coming from) that has to be sent over the wire. If each packet has it's own overhead of 42 bytes (number made up) and you need to send 500 unit updates, then sending each unit individually would ~20.5 Kilobytes of unavoidable overhead. That's not even counting the actual unit data. Instead, send a single large packet (or a couple of medium-sized packets) that says at the beginning "I have 500 unit updates" and only has an unavoidable overhead of 42 bytes (still made up number). The driver does try to do this for you, but often times it gets in the way by not sending the data when you expect it to ("But I still need 3 more bytes to fill my buffer! I'll send the rest of this when you give me those last 3 bytes."), which is not good when you're expecting low latency. Most people end up turning that feature off for their socket and manually combine packets to give them the best of both worlds.
Edit: I just looked up the actual overhead for a single network packet, and it ends up being ~82 bytes. So for my 500 unit example, the overhead just for the packet headers is ~40 Kilobytes. Ethernet has a packet size limit of 1500 bytes, which includes the IPv4 and TCP headers of ~40 bytes, so 1460 bytes per packet is about the size you'll be shooting for to get optimal data rates. Assuming 16 bytes per unit update you can fit around 90 units in a single packet, plus a little per-packet bookkeeping (timestamp and error checking if you go UDP, unit update count, etc.). My numbers were obtained here in case anyone wants to check facts.
thanks!
This helped me a lot.
With all these information I was thinking the next:
I make a queue m_MessageQueue; where I push_back all text I need to. I'll push_back only units that have been moved, upgraded, etc.
Then after a whole gamecycle I check that variable.
If I got something like this:
All these really small texts I can put into 1 long string and send it all together. I'm not sending the size of the string before I send the string. I'm making a buffer of TCHAR's ( for unicode ) that will hold the whole text.
Hm but wait, if I got 5 new orcs that I sended at the start to the client, and I move 1. How can I tell the client that THAT orc has been moved? I think I need an alias yes? So I send 4 numbers to the client for each unit, 'type alias xpos ypos". ( example: "0 19 163 140" ).
Am I thinking right for creating a network?
B. Jonathan
This helped me a lot.
With all these information I was thinking the next:
I make a queue m_MessageQueue; where I push_back all text I need to. I'll push_back only units that have been moved, upgraded, etc.
Then after a whole gamecycle I check that variable.
If I got something like this:
m_MessageQueue[0] = "0 10 50";
m_MessageQueue[1] = "5 30 150";
m_MessageQueue[....] = ".. .. ..";
m_MessageQueue[30] = "4 20 300";
All these really small texts I can put into 1 long string and send it all together. I'm not sending the size of the string before I send the string. I'm making a buffer of TCHAR's ( for unicode ) that will hold the whole text.
Hm but wait, if I got 5 new orcs that I sended at the start to the client, and I move 1. How can I tell the client that THAT orc has been moved? I think I need an alias yes? So I send 4 numbers to the client for each unit, 'type alias xpos ypos". ( example: "0 19 163 140" ).
Am I thinking right for creating a network?
B. Jonathan
Give an unique identifier to each orc (iterated starting from zero, or random, whatever), each time an orc moves emit a packet (or string if you want) that contains the orc's new position along with its identifier. You do not need to maintain a message queue with TCP because you can just send it directly over the internet - unless you are trying to push ludicrous amounts of data through your network link, your operating system's network subsystem TCP buffer will maintain a message queue of its own until the data can be sent.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement