Jump to content

  • Log In with Google      Sign In   
  • Create Account


Member Since 03 Jun 2003
Offline Last Active Yesterday, 08:35 PM

#5223317 In game chat as separate service - pros/cons?

Posted by hplus0603 on 14 April 2015 - 08:48 PM

I'm assuming you mean text chat, not voice chat.
If you have a "game host," that hosts 2-N players for reasonable values of N, then you can do in-game chat using RPC through the game host.
Chatting over RPC will only stop scaling if you want to support chatting between games, between arbitrary numbers of users.
Even there, a single server (not federated) should easily get you to 10,000 chatters, and could with some coaxing perhaps support up to 100,000 chatters (if carefully designed and profiled.)
Will off-the-shelf ejabberd work? Probably, yes! If there's a client library for Unity that you like, perhaps that's the easiest solution.

#5223315 Sending and receiving UDP broadcast message in C++ in Windows Phone.

Posted by hplus0603 on 14 April 2015 - 08:45 PM

Did you notice, that this code is in C#?

The translation betweem C++/CLR and C# should be pretty simple, if you need to do it.
Also, Microsoft samples are often available in many languages if you look -- I don't know about this one in particular.

Finally, if you already tracked down that the packet makes it to the receiver, but the process doesn't get it, then what have you done to debug that problem?
Have you enabled broadcast on the receiver?
Are you binding to the right port?
What does Wireshark say on the receiving machine?

#5222252 Multiplayer Services Server - Request and Brainstorming

Posted by hplus0603 on 09 April 2015 - 10:15 AM

Some bosses can be convinced, others cannot. The best way to convince someone in my opinion is to always be predictable and honest, and let them come to the right conclusion based on all available facts.

Now, if the lead has an estimate of 3 man-years, and you have a shorter estimate, have you asked your lead why the estimate is the way it is? Do you find that, when you estimte things, you often finish them before the time you estimated, so you know for a fact that your own estimates are trustworthy?

Separately: If your goal is to build a game, then the more you can get from open source or leasing/purchasing, the better, as long as it'a a good fit for the game. If you already have something "better than RakNet" for your game, then I'm not sure Photon is the best other option -- you could look at services like Parse, or PlayFab, or Gamedonia, for comparison.
Building everything from scratch is not the right thing to do, unless you are both very well funded, and you have already built several previous games, so that you know why you need to do it, and how to do it right.

#5222123 Level Loading on the Server

Posted by hplus0603 on 08 April 2015 - 03:35 PM

I think that could work. There's a risk that you would get a mis-match between the version used by the client and the version used on the server, if you're not careful (ideally automated) about how you build, release, and load your level geometry.
I don't know about navmesh libraries for C#, so I can't answer that question.
OBJ files sound great. You don't have to load the textures/materials from that file on the server. However, it might be useful to use a naming convention for various materials, if you have things like "lava" that deals damage when walked, or "clouds" which isn't actually walkable.

#5222085 Sending and receiving UDP broadcast message in C++ in Windows Phone.

Posted by hplus0603 on 08 April 2015 - 10:21 AM

Did you enable broadcast on the socket?
What tool do you use to test whether it "works" or not?
What does Wireshark say about outgoing UDP packets while you're trying to broadcast?

Also, there are more examples of this, such as: http://metronuggets.com/2013/03/18/how-to-send-and-receive-a-udp-broadcast-in-windows-phone-8-and-win8/
If you run this code, does that work? If so, what's different about your own code?

#5222084 Level Loading on the Server

Posted by hplus0603 on 08 April 2015 - 10:17 AM

It's hard to answer your queestions when your goals are not clearly stated.
What are your goals?
And then, given those goals, how are you trying to accomplish those?
I take it from your post that your client is written in Unity3D. Is your server running Unity3D or not?

#5221157 Interpolation Issue

Posted by hplus0603 on 03 April 2015 - 12:02 PM

Have you checked out http://www.mindcontrol.org/~hplus/epic/ ?

In general, to avoid jitter, you must either accept a guess about the future that will be wrong, or you must interpolate between two known-old positions. Which in this case means that, when you receive the position that's 160 ms old, your entity will just have reached the position at 320 ms old, and will start moving to the 160 ms old position over the next 160 ms.

#5221035 Sending and receiving UDP broadcast message in C++ in Windows Phone.

Posted by hplus0603 on 02 April 2015 - 05:47 PM

Did you look here? https://code.msdn.microsoft.com/windowsapps/DatagramSocket-sample-76a7d82b

#5221034 Gaming server

Posted by hplus0603 on 02 April 2015 - 05:46 PM

The forum FAQ has some information.

To give you better information, we need to know:
- what kind of game server? Is this for an existing game, like Counter-Strike or Minecraft, or a game you wrote?
- is it for matchmaking, scoreboards, community, etc?
- is it for gameplay, as in a MMO, or for "secure" game servers?
- how many players?
- how much can it cost to operate per concurrent player?
- what country are you in, and does the country of the game server matter?
- do you prefer Mac, Windows, Linux, BSD, ...
... the list goes on.

#5219331 Future proof scoreboard server design pattern

Posted by hplus0603 on 26 March 2015 - 09:15 AM

Are you sure about status field? Isn't HTTP code enough?

If the data is transferred outside of a HTTP-aware wrapper, then the HTTP status will be lost.
This can happen in a few ways:

1) Inside the application, it's common to pass along a dict<string, object> or similar representing the decoded body
2) If using on-disk caching separate from HTTP caching (which may be necessary when using out-of-band invalidation channels) you're reading a file, not a HTTP server, and would have to somehow synthesize a HTTP response if your unit-of-information is at the HTTP level
3) If you switch to other transports, such as message queues or push notifications, there are no HTTP status codes (see for example Facebook Mobile's use of MQTT)

#5219082 Future proof scoreboard server design pattern

Posted by hplus0603 on 25 March 2015 - 09:53 AM

For versioning, I prefer to put that in HTTP headers, rather than the URL. Accept: is one such header, for example.
You can treat a missing version header as "serve the latest."
Separately, for telling which client is making the request, you can look at the User-Agent: header -- you can arrange for your game to send a unique user agent which might be gamename/buildnumber, for example.

Also, there are a few things that you want to nail down ahead of time, and make them ALWAYS TRUE.
For example, if you use JSON, you may want the response to always contain the following fields:

status: "success" or "failure"
error: integer (if failure)
message: human-readable message (if failure)
data: actual-payload-data
Then wrap all the HTTP clients you use in a wrapper that can tell success from failure, and deliver the decoded payload to the application. A central library that does things right, and whose behavior you can easily reason about, goes a long way once the time comes to make changes.

You probably also want to make sure that your HTTP client always recognizes 300-level redirects and the Location: header, as well as a well-defined code (like 410) for what happens when you want to tell a client you're no longer prepared to serve it. Good user errors for 503 (temporarily unavailable) would be good, too.

Separately, you should build the client library to not blow up if the JSON fields come in a different order at different times. You should also not blow up if there are extra fields that you don't recognize -- just ignore them. Finally, if you expect a field, and it isn't there, you shouldn't blow up, but instead substitute some empty/null value in the decoded value; this may cause the game to detect an error, but should not throw an exception or cause a crash.

Using a version specifier is somewhat useful if your API evolves slowly. An alternative is to just tack the version number onto each service. https://api.yoursite.com/user3/ for users-version-3, and https://api.yoursite.com/purchase8/ for purchases-version-8. (This is similar to how we have interface names like IDirect3D12 -- it's a well-tested method that works.)

Oh, and always use HTTPS if at all possible.

#5218291 overlapped iocp send design problem

Posted by hplus0603 on 22 March 2015 - 12:27 PM

So, I wanted to send data 4096 byte by 4096. Should I keep that method or any better?

No, that's fine. Also, you're likely to see less than the full buffer available to send each time you tick the network generation, unless the user is in a very crowded area.

What should I do if WSASend returns with these errors

Wait until the next network tick and try again.

can WSASend operation complete with transferred bytes zero in any situation?

I suppose if you called on it to transfer zero bytes, it could complete successfully with zero bytes.
I would expect that if the connection was closed on the other end, you'd get an error, rather than a completion with zero.
If you don't call it with an argument of zero at any time, it's probably OK to treat this as an error condition.

#5218185 overlapped iocp send design problem

Posted by hplus0603 on 21 March 2015 - 08:19 PM

Yes, multiple WSABUFs (two of them) helps if you want to send the contents of the end-and-beginning at the same time.
You don't need to "first build the packet, and then copy into the ring buffer" -- just build the packet straight into the ring buffer.

#5218144 overlapped iocp send design problem

Posted by hplus0603 on 21 March 2015 - 03:20 PM

A typical server uses multiple queues interally. Let's assume you're using TCP:

First, there is a queue of "entities I need to update the player about." This is something like a list or set or whatever of pointers-to-entities, or, perhaps, ids-of-entities. These are dynamically allocated, but each entity has a fixed small size, so allocation is efficient.

Second, there is a queue of "data to actually write on the socket." This is something like one fixed-size array of bytes per player, often used like a ring buffer. This is pre-allocated once the player connects, so it's contiguous and a known quantity. Typical size of a record: 16 bytes (8 byte "next" pointer, 8 byte "entity" pointer.)

The "update" loop for a player then looks at how much available space there is in the outgoing buffer, and if there's enough, takes some of the queued entities, and generates updates for them into the outgoing ring buffer, and de-queues those entities from the update queue. (or puts them last, or whatever mechanism you use) Typical size: 1024-8192 bytes (too much may cause a lot of latency building up in the queue for slow connections)

Finally, the "send" loop for a player will, each time the socket comes back as writable, bytes between the current head of the ring buffer, and end of the ring buffer, and passed to send(). send() will dequeue as much as it can fit in local kernel buffers, but no more, and tell you how much that was. You remove that much from the ring buffer.

Note that, when you send data, you send many commands/updates in a single packet. You want to pack as much as possible in a single call to send().

If you're using UDP, then you remove the ring buffer. Instead, when it comes time to send a packet, you generate enough updates to fill whatever packet space you have. Let's say you make the maximum UDP datagram size 1200 bytes; this means you attempt to fill 1200 bytes of updates from the head of the queue (minus whatever protocol overhead you're using for sequence numbers or whatnot.) You may also want to put the entity update links into an "outstanding updates" queue if you receive acks from the other end. This "generate data and call send()" happens in one go, and thus you only need a single static buffer that is the size of the maximal packet size, to share between all possible senders.

When there are 300 players in one area, you don't generate data for 300 players at once. Instead, you enqueue 300 players' worth of entity updates into the list of entities, and generate 1200 bytes at a time, and repeat this until there are no entities to update. (Although you will always have entities to update unless the player is alone in the world :-)

Also, when a socket is sendable, it means that a call to send() will not block; it will dequeue your data and put it in some kernel/network buffer. Thus, you don't ever need multiple outstanding send requests. If you use overlapped I/O, then you will typically keep one overlapped struct and one buffer per player, pre-allocated, just like the ring buffer in the TCP case (and, for overlapped I/O with TCP, that's exactly what you will be using.)

#5218142 Server-client or P2P, is one more suited for a style of game?

Posted by hplus0603 on 21 March 2015 - 03:10 PM

Note that there are two different topologies here!

One is your physical networking topology: Does each of your players find other players on their own, or does the traffic go through a central server?

The second is your gaming topology: Does each of your players send/receive updates to/from all other players, or is one player elected "host/leader/serer" and receives/collates/broadcasts for all others, or do you have a central server doing that?

The typical solution (that is most common, most robust, fits most cases, etc) is:
- discovery of other players (matchmaking) and making sure their firewalls cooperate (NAT punch-through) is coordinated by a central serer
- one player is assigned "host" of the game, and the other players connect to that player
- once the match is made and the game is started, the central matchmaker server doesn't see more traffic from the players

This is, at the game level, a client/server set-up, but at the physical networking layer, a hybrid between central-server, and clients-talking-to-clients, so from a physical networking point of view, it counts as being "peer to peer" in that the central server isn't involved in gameplay traffic.