Jump to content

  • Log In with Google      Sign In   
  • Create Account


Member Since 03 Jun 2003
Online Last Active Today, 05:46 PM

#5240324 Java Kryonet server never sends connected() packet?

Posted by on 14 July 2015 - 02:34 PM

This seems like a Java packaging problem, not strictly a networking problem.

What you should focus on is this: What is the difference between "run" and "dist"?

For example: Does it use obfuscation? Does your code (or networking) use method names/reflection, that might break because of that?

If you can make an exhaustive list of all the things that differ between "run" and "dist," then figure out how each of those things might affect your networking code, then you will have the solution.

#5240273 How to send boost::archive::text_oarchive with socket?

Posted by on 14 July 2015 - 10:25 AM

ofstream fs("text.txt");
socket.send({127, 0, 0, 1, serverPort}, &fs, sizeof(fs));
At the risk of seeming harsh, I would suggest that this code shows to me that you do not yet have an understanding of C++, pointers, and memory, that is necessary to successfully build a networking layer.
I suggest that you spend another year or two doing C++ development on a local machine/host/game, to the point where you actually understand things like memory layout of objects, cost of disk versus cost of memory, and other such important concepts. Then perhaps try again for something networked.

#5240074 best way to connect 2 random people around the world in winsock

Posted by on 13 July 2015 - 09:02 AM

The FAQ (linked at the top of the networking forum topic list) has some links about NAT punch-through. For example, http://www.enchantedage.com/node/8

#5239128 Sending and Recieving Game Map Files.

Posted by on 08 July 2015 - 10:42 PM

How to determine how often is "too often":
First, you figure out what feels alright to your users.
Then, you measure how much load it would be if a representative number of users did that.
If you can keep up with that load, you're done; else you have to either compromise on "what feels alright" or you'll have to optimize your system.

#5238376 Implementing multiplayer in MOBA-like game

Posted by on 04 July 2015 - 01:48 PM

If the server was made in C++, can I send the whole structs over the socket? Beacause I've read somewhere that its not recommended but didn't really understand this.

There are several layers to decode here.

First, in a C or C++ program, a "struct" is laid out in memory in a certain way. This way can be specific to each compiler (or even to specific versions of a compiler) as well as specific to particular alignment rules depending on the CPU architecture.

"Sending a struct" really just means "sending a raw set of bytes that happened to be written by the compiler as a struct."

Yes, you can send a raw set of bytes -- in some respect, that is the only thing you can ever really send. Everything else has to go through some form of "marhsalling" on the sending side, and "demarshalling" on the receiving end. For example, to send a variable-length string, the sending side would have to first send the length of the string, and then the actual string data; the receiving end would first read the length, and then reserve enough space to receive the string data and return to the program.

The reason structs are "not recommended" is because you don't have full control over the layout. A struct that is laid out in one particular way on a 64-bit Intel platform, may be laid out a totally different way for a 32-bit ARM running in 16-bit Thumb mode. Specifically, the amount of padding inserted by the compiler for performance / alignment rules may differ.
A secondary concern is that of binary representation. IEEE-754 is pretty universal, and using "float" and "double" almost always means the same thing, and two's complement representation for integer values is also something that everybody does by now. (Fourty years ago, this was not true.)
But -- sizeof(size_t) may be different on different machines. sizeof(int) is 2 on Arduinos, and 4 on Raspberry Pis. And, also importantly, while the world is largely skewing towards little-endian representations these days, there still exist big-endian platforms and implementations out there. All of these are things that COULD change between sender and receiver, especially if you are multi-platform, or define an open protocol which multiple parties can implement.

Again, in networking, what really matters is the bytes that are sent on the wire. As long as sender and receiver agree on this, to an extremely high level of precision and determinism, any way to get there is fair game.
Depending on which language you're using, and how familiar you are with the language, you may not yet have the skills and experience needed to understand where these things will vary, and why -- if so, you're probably better off either using a marshaling library of some sort (protocol buffers) or sharpening your tools on lighter-weight systems programming tasks (binary file formats, 3D graphics, etc.)

#5238244 Implementing multiplayer in MOBA-like game

Posted by on 03 July 2015 - 02:13 PM

Protocol buffers are alright -- they given you good rigor for data formats, yet some amount of flexibility.
However, they are bigger than the payload needs to be for a game, if you can assume that all players/clients/servers use the same version.

Game networking is built around "only send what you need, no more" and "when sending, only send the precision you need, no more."
For example, if the coordinate of a user is between -4000m and +4000m, and you need centimeter precision, that means you have about 800,000 distinct values.
Twenty bits will allow you to send 1024*1024 values, so a range from -5242.88 to 5242.87 would let you send one value in 20 bits instead of one value in 32 bits, for a cool 37.5% size savings!
Keep applying this thinking to each piece of data, and either don't send it (if you can calculate it) or trim bits if you don't need the full precision, and you will make for much smaller packets.

Note: If there are 8 players, each of which has 100 bytes of data, that's 800 bytes in a single outgoing packet to a single player for a single tick (because that's the updating state for each other player, plus the sync state that lets the player know what the server thinks he's doing.)
Savings there matter. However, because of the overhead of IP (20 bytes,) UDP (8 bytes,) and/or TCP (20 bytes) protocols, and the packetization of underlying networks, there exists a minimum below which you really don't gain much.

If we assume that the underlying network uses ATM, with 48 byte payloads, and IP + UDP (28 bytes of overhead,) then the minimum effective size is 20 bytes of payload (a single cell); the next iteration is 68 bytes of payload (two cells); etc. Other framing systems have different specific grouping rules. A rule of thumb is that if you're sending less than 100 bytes, further savings are better had by sending less frequently, rather than by making the packet smaller. Another rule of thumb is that it's always better to send 1 packet with data A and B to the same destination, rather than splitting it into two packets, one with data A and one with data B -- until some upper limit. For UDP on the internet, that upper limit is at least 1200 bytes, and sometimes a bit more. Various magic constants include Ethernet frame size, IPv6 minimum MTU, WiFi payload size, and 4G mobile data packet size. The often-quoted 576 byte MTU value for dial-up internet is largely a thing of the past, though (luckily :-)

#5237726 Implementing multiplayer in MOBA-like game

Posted by on 30 June 2015 - 01:44 PM

packets" of data from the server are send something like 20 times per second, and the client somehow interpolates in between to get the smooth gameplay. Do you think its necessary to do this even if there is an 8 player limit

And I'm sending only the most important data parsed in JSON strings over the network.

How much JSON? 200 bytes per player? Times 8 players? Times 60 packets per second?
With 40 bytes overhead per packet (assuming TCP, as you use multiple sockets,) you will see about 6.4 Mbps of upstream bandwidth from the server, and 800 kbps downstream for each client.

Can this be done? Yes! Would this be a good idea in a commercial situation? Not really.

#5237585 Implementing multiplayer in MOBA-like game

Posted by on 29 June 2015 - 06:22 PM

As far as networking, I would start looking at Sockets and object serialization until you get comfortable passing objects back and forth and then upgrade to passing only significant bytes back and forth.

While everyone is entitled to offer their own advice, I would disagree with this advice. If you're getting started with networking, possibly across different languages, simple binary blobs-of-bytes, or even just text strings with delimiters, are a much better place to start.
Object serialization is a very different concept, very poorly matched to real-time gaming data, and comes with its own special set of terror related to versioning, security, and compatibility. Can be great in certain situations -- I don't think this is one of them.

#5237510 Sending and Recieving Game Map Files.

Posted by on 29 June 2015 - 10:21 AM

I had a thought that the client can spam the refresh

This is known as a "denial of service attack" and is something you have to work around server-side.
Putting a timer on the refresh button on the client isn't particularly great, because a determined attacker can just make the same kind of request without using your client (and thus not being limited by the button.)
A better way to do it is to remember the last time a refresh request came in, and if the refresh request is too early, either ignore it, or pend it until a reasonable time has expired. If multiple refresh requests come in at the same time, pend them all, and resolve them with the same data once the final timer has expired.

If the goal is to show active server instances (which is perhaps different from "all maps" -- because many servers can use the same map, and some maps may not have active servers) then perhaps a better idea is to put state in the protocol. When the client first connects, it gets sent a list of all servers automatically. Then, as new servers connect, or servers disconnect, the clients are sent an update with the deltas, every so often.
You'll also want to use timeouts and keep-alive messages to make sure that idle connections don't take up resources for too long, but that's best handled at the connection layer, so it applies to anything your game does.

#5237508 Trying to emulate "typical" internet conditions

Posted by on 29 June 2015 - 10:17 AM

Out of interest, why is this?

One common source of duplication or re-ordering is when routes change, or new routes are established, which only happens rarely, and generally happens most when a new flow is established.

WiFi connections may perhaps re-order, or even duplicate, packets at any time -- I haven't measured that. I know they add significant jitter to the latency.

Since I am using UDP there is no connection per sé from the network's point of view, right?

There are not "connections" at layer 4-and-up, but there are "flows" at the lower network layers.
Your NAT firewall will have to remember outgoing packets for some time, so return/responses can be properly re-written.
Routers will have to remember routing decisions for previous packets, because looking up brand new routes for each packet is terribly inefficient.
The network industry captures this concept into the name "flow," which is generally identified by a tuple that starts with source IP, destination IP, and protocol ID, and then also adds protocol-specific additional data (such as source port and destination port for TCP or UDP.)
Routers will then have something like a big hash table of "flow" to "routing decision," with a time-out, and each time a packet is routed, that time-out is reset.

When a router sees a new flow, it may need to hold the first packet while it's looking up the routing decision.
Meanwhile, a second packet may be sent, and may arrive after the routing decision has been made, but before the router has had time to forward the held packet.
The result is re-ordering of packets when a new flow is looked-up. The most common source of new flows is simply new "sessions" (at the user level) although this can also happen if routes are changed for reasons such as maintenance, failure, cost changes, etc.

#5237384 Trying to emulate "typical" internet conditions

Posted by on 28 June 2015 - 07:37 PM

I don't think that's aggressive enough. I'd suggest upping packet loss to 10%, and round-trip latency to 250 milliseconds or more.

Duplication and re-ordering are much less of a problem once a connection has been established, but because it happens, it's good that you have a small amount of packets in that class. Upping it to 1% each would probably help flush out some problems.

And if you don't think packet loss is real, my Comcast cable connection, going from me to Google data centers a few miles away, have about 1% constant loss of UDP packets, day or night, and have done so for years.

#5237383 Implementing multiplayer in MOBA-like game

Posted by on 28 June 2015 - 07:32 PM

The cool thing with networking is that one end doesn't know what language/tool/whatever was used to implement the other end.
Only bits on the wire matter.
That being said, if you use complex systems like Java remoting or serialization, then you will have more trouble trying to match that on the C++ side. Simple packets made of bytes in well-defined order are much easier to get robust cross-platform and cross-language.

Thread-per-client is an anti-pattern. Sometimes, you have to do it (such as on older versions of the JDK) but you really should be using Java NIO. Even if you don't, then the threads should only be used to read the sockets; the actual world/game simulation should most likely be on a single thread, unless your system is really, really, special, and you have extensive distributed simulation experience.

Also, sending only inputs to the server means that the server and the client will have to agree on what happens when the client presses "forward" and then keeps it down for 0.28 seconds. How many simulation ticks are those? How is collision detected? Building the same physics engine in both Java and C++ is a big task (unless your simulation is trivial.)

Now, if you really really want to build the networking side of the client in Java, but the rest of the client in C++, this can be done. You'd have to build the "main" of the project in Java, and then expose your C++ code through a JNI interface. Have the Java application run the main loop, run the socket/s, and communicate to the C++ code using JNI each frame. A bunch of games on Android works a bit like this, because the UI is generally in Java, but portable games are generally written in C++, so it can be done. It wouldn't be the simplest way to do it, though. And, if your'e not familiar with Java NIO, and want to create threads-per-socket, then you probably aren't gaining much from using Java anyway.

I'm not saying what you want to do can't be done. I'm just saying that you're not choosing the simplest possible way to build a multiplayer game.
Good luck with your project!

#5237198 Sending and Recieving Game Map Files.

Posted by on 27 June 2015 - 10:30 PM

Thats not always true.

I thought it was pretty clear that I was being ironic :-)

Software development is, generally, done to make a business money. If the business isn't really in the software business, but just automates tasks to save on manual labor, then as soon as it "works" it's "done."(Automated) testing is for people who want to be able to change things, which generally means software-development businesses.

#5237165 Sending and Recieving Game Map Files.

Posted by on 27 June 2015 - 04:42 PM

It's not that simple because it's a huge Frankenstein system with tons of hard coded references to said directories ;)

But you do have a full integration test setup, so you can just change it, run the tests in sandbox, and see what breaks, right?
I mean, nobody would build a system they couldn't test, right?

#5237111 Sending and Recieving Game Map Files.

Posted by on 27 June 2015 - 10:40 AM

The fast and efficient solution to that is to create a filename prefix tree.
For each file, create one or two levels of directories:

foobarfile.dat -> fo/foob/foobarfile.dat
Iteration then means recursively iterating the directory in question. How many characters per level, and how many levels, depends on the spcifics of your data.
This works extra well when the file names are a hash of the contents, because each level of the prefix will have an even spread of data.

The "real" solution is to realize that a file system isn't the right solution for that use case, and start using a database :-)