Sign in to follow this  
JPulham

PHP, master servers and STDOUT

Recommended Posts

I'm writing a peer to peer game which needs a master server to keep track of all the games. I was thinking of using PHP and MySQl...so I could post it straight on to the web site where it will be downloaded from. This leads to my first question: 1)Is PHP and My SQL suitable for a master server or should I use another method? Also...how can I get the table data to the sending computer? 2)could I use stdout and for loops to send the data to the computer who sent the HTTP request, and what is the prototype for STDOUT in PHP? 3)Finally...how do I receive this info...is there a good premade class or tutorial on this kinda stuff? I'm using Raknet but WinSock would also work. Thanks in advanced...

Share this post


Link to post
Share on other sites
If PHP runs as part of the web server, then anything you print will go out to the client computer.

If you want to make a HTTP request from a client computer, you might want to take a look at my lightweight HTTP-GET library.

If you want to do NAT punch-through introduction from your master server, however, HTTP and PHP is not the right solution, because you need to be listening on a UDP port.

Share this post


Link to post
Share on other sites
PHP for the master server is fine, however, you'll need to be able to use the PHP sockets library.

When a server connects to the master server, you should connect back to it to make sure it's a real server (and not firewalled), before listing it in the server list. Otherwise, you'll end up with heaps of inaccessible servers in the list.

You should also make some kind of periodic job (Cron?) which checks that existing servers are still up, and if not removes them from the list.

There's no need to use stdout (I'm not even sure if you can) to write output to a HTTP client - you can simply use echo()

Mark

Share this post


Link to post
Share on other sites
so would something like this work:

HTTP-GET: http://mygamesite/thegame/server.php?action=get

if($action==get)
{
echo($howmanyserves)
for(not end of database)
{
echo($name);
echo($type);
echo($IP);
}
}

and using the HTTP get Read() to get the return from echo?
also, how to I do timed test on servers and how often? (i.e every minute say 'are you there')

Share this post


Link to post
Share on other sites
Yes, that might work. You'd need to add some kind of separator between the server fields, though, or they'll all run together as simple text. I would probably return the data as XML, though, which is easy enough to print.

I would suggest that the servers tell the registrar about their existence every so often, instead. The server can then drop servers that it hasn't heard from in X minutes. If you keep a database, you'd just make the "current servers" query be "servers whose last timestamp is newer than (now - X minutes)", and keep the old records around. That way, you need no periodic task to remove things from the database just so you don't show old stuff.

Share this post


Link to post
Share on other sites
how would I read the XML?
I have irrlicht, could I use IrrXML...or is there a better library?
And how would I read in the info?

Share this post


Link to post
Share on other sites
To print the info (using Postgres and PHP running inside Apache):


<?php
print( "<data>\n" );
$r = pg_query( "select ip, name, lasttime from servers where lasttime > " . timeAsString(time()-5*60) );
$nr = pg_numrows( $r );
for( $i = 0; $i < $nr; ++$i ) {
$a = pg_fetch_array( $r, $i );
print( "<server ip='$a[ip]' name='$a[name]' lasttime='$a[lasttime]'/>\n" );
}
print( "</data>\n" );
?>





To read the data from the server, use something like HTTP-GET.

To parse the XML data once you've read it, use whatever XML parser you want. I don't know about IrrXML, but if it's an XML parser that can parse a text chunk in memory, then that should do it. An alternative is XMLSCAN, my ultra-lightweight, very fast XML parser.


// simple utility function
XMLNode * find( XMLNode * p, XMLScanner::Token::Kind kind, char const * name )
{
XMLNode * c = p->child( 0 );
while( c ) {
if( c->token().kind == kind && c->token().keyIs( name ) ) {
return c;
}
c = c->next();
}
return 0;
}


// how to parse in-memory XML data of length xmlDataLength,
// pointed at by xmlData.
XMLDom * dom = new XMLDom( xmlData, xmlDataLength, 0 );
if( dom->error() ) {
throw runtime_error( std::string( "bad XML format: " ) + dom->error() );
}
XMLNode * root = dom->root();
XMLNode * data = find( root, XMLScanner::Token::Tag, "data" );
XMLNode * server = data->child( 0 );
while( server ) {
if( server->token().keyIs( "server" ) ) {
XMLNode * ip = find( root, XMLScanner::Token::Attribute, "ip" );
XMLNode * name = find( root, XMLScanner::Token::Attribute, "name" );
std::string ipStr, nameStr;
XMLUtil::ToText( ip, ipStr );
XMLUtil::ToText( name, nameStr );
doWhateverWithYourServerInfo( ipStr, nameStr );
}
server = server->next();
}
delete dom;





Note that the code hasn't been compiled, so may have some typos in it.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
what about speed and fluidity of game play? does using a myswl server with php slow the gaming experience down?

data can only travel as fast as the script can connect with the db right?

thnx

Share this post


Link to post
Share on other sites
You're talking about a server registration system, right? What does that have to do with gameplay? Once you're connected to a server, you don't need the server list anymore.

Even so, fluidity of the matchmaking doesn't matter, as long as you use non-blocking or polled (select()) I/O on the sockets, leaving the program free to do other things while waiting for the list server. HTTP-GET does this, btw (as it has a polled interface).

Share this post


Link to post
Share on other sites
I'll probably feed the input into IrrXML...
thanks for the comments...XML never crossed my mind, it should of realy :P.

Share this post


Link to post
Share on other sites
Very sorry to bring back an old post but I have a related question.

Basically I'm wondering at how efficient it is to write your master server through PHP versus a small C++ app. The only major benefit I can think of for using PHP is an extreme level of portability so your master server could work on any platform that supports PHP/MySQL. On the other hand, PHP is an interpreted language so is bound to run a bit slower and have more overhead. I'd want to use the master server machine for other things as well so keeping the master server as optimal as possible is quite important to me, or is this in itself a bad idea. Should a master server always run on a dedicated machine?

Also, is it a good idea to distribute the heartbeat checks over a number of frames instead of just checking a ton of servers at once or is spawning a low priority thread to do this just as sufficient?

Thanks!

p.s. a benchmark to illustrate my point showing the difference in performance between interpreted and compiled apps:
http://www.osnews.com/story.php?news_id=5602&page=3

Share this post


Link to post
Share on other sites
Quote:
Original post by Dirge
Basically I'm wondering at how efficient it is to write your master server through PHP versus a small C++ app.


That is a case of premature optimisation. Remember that the master server doesn't actually need to do anything, except when a server registers / unregisters, and periodic checks that existing ones are still there.

If your master server has to do so much work that it's going to be inefficient, then you should refactor it then.

The major benefit of using C++ is that you may be able to reuse some code, if your client/ server is written in C++ - this strikes me as the main requirement.

Because a master server *MUST* connect back to the servers speaking your game protocol to check that they are really there, aren't blocked by firewalls or NAT'd in an unacceptable way, and aren't totallly made-up etc, it may have to reuse some code from your game client/server. You may find it more convenient to write the master server in C++ because of this.

Quote:

The only major benefit I can think of for using PHP is an extreme level of portability...


It's a nonissue. It doesn't matter. Your PHP server app won't be portable anyway, insofar as, it will require a very specific version of PHP and specific settings. Those should be documented and checked at runtime (to prevent errors later). Portability is not important enough for this app- after all, there is only going to be *one* instance in the *world*, right?

Quote:

Also, is it a good idea to distribute the heartbeat checks over a number of frames instead of just checking a ton of servers at once or is spawning a low priority thread to do this just as sufficient?


I have no idea what that means.

Spawning a low priority thread to do anything is probably a sign of a design fault - you should not rely on the operating system's scheduler to behave in a specific way in order to achieve a given behaviour - that is just abuse of it.

I take it you're talking about either the client or the server now.

It is likely that it will be the best design for a client or server, to have all the networking code in a single thread, although you may decide otherwise.

Mark

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this