xestre Posted March 2, 2014 Share Posted March 2, 2014 Recently I started getting into server queries, attempting to retrieve data from game servers. I started with the source games (think of CS:S, TF2 etc etc) and it works quite well my script shown below. <?php $handle = fsockopen("udp://127.0.0.1", 7777, $errno, $errstr); stream_set_timeout($handle, 2); fwrite($handle, "\xff\xff\xff\xff\x54\x53\x6f\x75\x72\x63\x65\x20\x45\x6e\x67\x69\x6e\x65\x20\x51\x75\x65\x72\x79\x00"); $response = fread($handle, 256); echo $response; ?> https://developer.valvesoftware.com/wiki/Server_queries#A2S_INFO you'll see what is needed in order to request data. However the problem arises when I want to query an other game, that is not of the source engine. Given the picture below. It needs to be a non-blocking UDP connection, but I've got no idea how to create such request. I know that for the first 3 bytes I need: 0x4d, 0x49, 0x56, however how I do continue? Can someone help me out with PHP? Thanks in advance. Quote Link to comment Share on other sites More sharing options...
xestre Posted March 3, 2014 Author Share Posted March 3, 2014 Sorry for bumping, but I really need help with this. Anyone with experience in this field please reply. Quote Link to comment Share on other sites More sharing options...
Ansego Posted June 13, 2014 Share Posted June 13, 2014 Bump. Curious too, I am writing socket code atm, trying to get a generic code for multiple games but having no luck due to the variables are different for each game, though I would of expected some kind of standardisation with the variables ie host, server_type, players, max_player, name etc. One thing I do keep running into is: $port is a reserved variable so be aware of that if you are running through a function or set a constant. The code you have provided for TF2 gives output: ITF2 Servercp_dustbowltfTeam Fortressdw2198641i%8@TF2Stats,alltalk,cp,increased_maxplayers,norespawntime,respawntimes But I have noticed for games like Minecraft they use the tcp:// other then the udp:// as shown below (requires a handshake): @stream_socket_client('tcp://'.$url.':'.$xport, $errno, $errstr, 1) Also not 100% on the hex command lines, these would also vary per server type (I assume): http://ddecode.com/hexdecoder/?results=552bf941214641e4743cf5709401132a \xff\xff\xff\xff\x54\x53\x6f\x75\x72\x63\x65\x20\x45\x6e\x67\x69\x6e\x65\x20\x51\x75\x65\x72\x79\x00 This is details for Steam queries for source engine/valve (I don't know how to make use of it): https://developer.valvesoftware.com/wiki/Server_queries Wish us both luck. If I find something I'll share it. If any GURU's out there that know about sockets look forward in hearing from you too. Quote Link to comment Share on other sites More sharing options...
kicken Posted June 14, 2014 Share Posted June 14, 2014 I prefer to make PHP classes that resemble the structures/packets you'll be using to query a server. You can then either use the __toString or make a pack method that will generate the byte sequences that need sent. For example for the Source server header packet might be represented as such: class SourceHeader { public $header; public $id; public $total; public $number; public $size; public function pack(){ return pack("VVCCv", $this->header, $this->id, $this->total, $this->number, $this->size); } public static function createFromBuffer($buffer){ $fields = unpack("Vheader/Vid/Ctotal/Cnumber/vsize", $buffer); $obj = new self; $obj->header = $fields['header']; $obj->id = $fields['id']; $obj->total = $fields['total']; $obj->number = $fields['number']; $obj->size = $fields['size']; return $obj; } } Of course you'll need to add some extra code to handle things like different versions possibly returning more or less fields. For example in the above if $obj->header&0x800000 == 1 then there are two additional fields size (another one separate from the one listed) and crc32 sum representing the size and checksum of the uncompressed data. Also the size field listed may or may not exist depending on the engine and it's version. By making things classes like that though it helps keep things organized, readable, and lets you only have to mess with generating the binary strings in one place. As for the UDP sockets, you'd just create one using stream_socket_client, send data using stream_socket_sendto, and read data using stream_socket_recvfrom. Such as: $header = new SourceHeader; $header->header = -1; $socket = stream_socket_client('udp://game.server.address:port'); stream_socket_sendto($socket, $header->pack()); I've never messed with querying game servers, so I have no idea how exactly the interactions go for it. It has also been quite a while since I've done anything with UDP sockets, so the above is based on memory and a few minutes looking over the php and valve manuals. There are likely bugs that would need worked out, and definitally error handling that needs worked in. Quote Link to comment Share on other sites More sharing options...
dodgeitorelse3 Posted June 17, 2014 Share Posted June 17, 2014 querying game servers is sort of tricky. One reason is due to the games changing engines which then makes any code you have not work right or at all. For a reference as how to accomplish the task go to http://www.greycube.com/site/download.php?view.56 look into lgsl/lgsl_files/lgsl_class.php as well as lgsl/lgsl_files/lgsl_protocol.php some of the queries are outdated due to engine changes for some games and some other games have been added that were not included in the download file but just search forums, you will find all the answers there. good luck Quote Link to comment Share on other sites More sharing options...
Psycho Posted June 17, 2014 Share Posted June 17, 2014 The data that can be returned from the different game server and the optional parameters that can be used when making those queries will vary greatly. But, instead of trying to build the low level code to make those connections and retrieve data, you might want to see if there is already something existing that supports all the game servers you want such as this: http://gameq.sourceforge.net/ (>170 games supported). Although, I see that there are several more current bames not supported (BF3 & BF4). I would start with a package like that. Then for the other games you want to support, see if there are any similar existing packages. Then you can build a middle-tier class that will communicate with them all. E.g. based on the game data being requested, your class would determine which package to use and return the data in a consistent format. Then you would have just one interface for getting data. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.