Results 1 to 2 of 2

Thread: PHP to C# - Sockets, or whatever, I dunno

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    PHP to C# - Sockets, or whatever, I dunno

    Hi,

    Sorry for the confusing title, as will become clear shortly this is completely unfamiliar territory for me, so I have really no clue what I'm doing.


    Anyway, I am trying to interact with a game server for Call of Duty: Black Ops, this is usually called 'remote console'. I had no idea where to start so I googled around a bit and found a complete web-based remote console implementation (I did not try it but I am assuming it works). Unfortunately, it is in PHP, about which I know absolutely nothing.

    The most important file in the PHP implementation, I think, is this:
    php Code:
    1. <?php defined('SYSPATH') or die('No direct script access.');
    2. /**
    3.  * Remote console connection
    4.  *
    5.  * @author      EpicLegion
    6.  * @package     rcon
    7.  * @subpackage  lib
    8.  */
    9. class Rcon {
    10.  
    11.     /**
    12.      * Socket res
    13.      *
    14.      * @var resource
    15.      */
    16.     protected $socket = NULL;
    17.  
    18.     /**
    19.      * Password
    20.      *
    21.      * @var string
    22.      */
    23.     protected $password = '';
    24.  
    25.     /**
    26.      * Host (IP)
    27.      *
    28.      * @var string
    29.      */
    30.     protected $host = '';
    31.  
    32.     /**
    33.      * Serve port
    34.      * @var int
    35.      */
    36.     protected $port = 3074;
    37.  
    38.     /**
    39.      * Constructor
    40.      *
    41.      * @param   string  $host
    42.      * @param   int     $port
    43.      * @param   string  $password
    44.      */
    45.     public function __construct($host = '', $port = 3074, $password = '')
    46.     {
    47.         $this->host = $host;
    48.         $this->port = $port;
    49.         $this->password = $password;
    50.     }
    51.  
    52.     /**
    53.      * Send command
    54.      *
    55.      * @param   string      $command
    56.      * @param   bool        $return_response
    57.      * @throws  Exception
    58.      * @return  mixed
    59.      */
    60.     public function command($command, $return_response = TRUE)
    61.     {
    62.         // No connection
    63.         if(!$this->socket OR !is_resource($this->socket))
    64.         {
    65.             throw new Exception('You must connect to remote console before issuing commands');
    66.         }
    67.  
    68.         // Send command
    69.         fwrite($this->socket, "\xff\xff\xff\xff\x00".$this->password.' '.$command."\x00");
    70.  
    71.         // Wait for response?
    72.         if($return_response)
    73.         {
    74.             // Retrieve reponse
    75.             $response = $this->get_response();
    76.  
    77.             // Invalid password?
    78.             if(trim($response) == 'Invalid password.')
    79.             {
    80.                 throw new Exception('Invalid remote console password.');
    81.             }
    82.  
    83.             return $response;
    84.         }
    85.     }
    86.  
    87.     /**
    88.      * Connect to rcon
    89.      *
    90.      * @throws  Exception
    91.      */
    92.     public function connect()
    93.     {
    94.         // Errors
    95.         $errno = 0;
    96.         $errstr = '';
    97.  
    98.         // Open socket
    99.         $this->socket = fsockopen('udp://'.$this->host, $this->port, $errno, $errstr, 5);
    100.  
    101.         // Invalid?
    102.         if(!$this->socket)
    103.         {
    104.             throw new Exception('Cannot connect to remote console');
    105.         }
    106.     }
    107.  
    108.     /**
    109.      * Disconnect
    110.      */
    111.     public function disconnect()
    112.     {
    113.         fclose($this->socket);
    114.     }
    115.  
    116.     /**
    117.      * Read response
    118.      *
    119.      * @return  string
    120.      */
    121.     public function get_response()
    122.     {
    123.         // Var containing response
    124.         $response = '';
    125.  
    126.         // Set socket timeout
    127.         stream_set_timeout($this->socket, 0, 7e5);
    128.  
    129.         // Lol how rare
    130.         do
    131.         {
    132.             // Read 8kb
    133.             $stream_read = fread($this->socket, 8192);
    134.  
    135.             // End of response?
    136.             if(strpos($stream_read, "\x00") !== FALSE)
    137.             {
    138.                 // Cut
    139.                 $stream_read = substr($stream_read, 0, strpos($stream_read, "\x00"));
    140.             }
    141.  
    142.             // Get socket info
    143.             $stream_info = stream_get_meta_data($this->socket);
    144.  
    145.             // Append
    146.             $response .= substr(trim($stream_read, "\x0a"), 11);
    147.         }
    148.         while(!$stream_info['timed_out']);
    149.  
    150.         // Return
    151.         return $response;
    152.     }
    153.  
    154.     /**
    155.      * Get socket resource
    156.      *
    157.      * @return  resource
    158.      */
    159.     public function get_socket()
    160.     {
    161.         return $this->socket;
    162.     }
    163.  
    164.     /**
    165.      * Set RCON password
    166.      *
    167.      * @param   string  $password
    168.      */
    169.     public function set_password($password = '')
    170.     {
    171.         $this->password = $password;
    172.     }
    173.  
    174.     /**
    175.      * Set server connection details
    176.      *
    177.      * @param   string  $host
    178.      * @param   int     $port
    179.      */
    180.     public function set_server_info($host = '', $port = 3074)
    181.     {
    182.         $this->host = $host;
    183.         $this->port = $port;
    184.     }
    185. }

    I can logically split this file into three parts:
    1. 'Properties' like Host, Port and Password, including setters / getters / constructor, etc. I can manage this obviously.
    2. Connecting and sending commands to the host, as well as receiving a response. This is what I'm having trouble with.
    3. Parsing the response into readable chunks. I am not here yet (though I might need some help with that too), I'd rather get item 2 working first.



    So, I looked around a bit and found the UdpClient class. The command to connect in the PHP source uses "udp:// ..." so I thought that would be a good place to start.


    I wrote this class as a translation of the PHP code, at least the connecting and sending a command part:
    csharp Code:
    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Net;
    5. using System.Net.Sockets;
    6. using System.Text;
    7. using System.Threading;
    8.  
    9. namespace BlackOpsRconTest
    10. {
    11.     public class Rcon
    12.     {
    13.         public Rcon(string host, string password)
    14.         {
    15.             this.Host = host;
    16.             this.Port = 3074; // I don't think this can ever change for this game
    17.             this.Password = password;
    18.  
    19.             client = new UdpClient();
    20.         }
    21.  
    22.         public string Host { get; set; }
    23.         public int Port { get; set; }
    24.         public string Password { get; set; }
    25.  
    26.         private readonly UdpClient client;
    27.  
    28.         private static bool messageReceived = false;
    29.  
    30.         public void Connect()
    31.         {
    32.             client.Connect(this.Host, this.Port);
    33.         }
    34.  
    35.         public void Disconnect()
    36.         {
    37.             client.Close();
    38.         }
    39.        
    40.         public void SendCommand(string command)
    41.         {
    42.             // preCommand is supposed to be the '\xff\xff\xff\xff\x00' stuff...
    43.             string preCommand = new String(Convert.ToChar(0xff), 4);
    44.             preCommand += Convert.ToChar(0x00);
    45.  
    46.             // get the bytes to send
    47.             // this spells     \xff\xff\xff\xff\x00<password> <command>\x00
    48.             // as in the PHP source...
    49.             var commandBytes = Encoding.ASCII.GetBytes(String.Format("{0}{1} {2}{3}",
    50.                                                                      preCommand,
    51.                                                                      this.Password,
    52.                                                                      command,
    53.                                                                      Convert.ToChar(0x00)));
    54.             // Send it!
    55.             client.Send(commandBytes, commandBytes.Length);
    56.  
    57.  
    58.             // Now listen for response.
    59.             IPEndPoint e = new IPEndPoint(IPAddress.Any, this.Port);
    60.             UdpState s = new UdpState();
    61.             s.e = e;
    62.             s.u = client;
    63.  
    64.             Console.WriteLine("listening for messages");
    65.             client.BeginReceive(new AsyncCallback(ReceiveCallback), s);
    66.  
    67.             // Do some work while we wait for a message. For this example,
    68.             // we'll just sleep
    69.             while (!messageReceived)
    70.             {
    71.                 Thread.Sleep(100);
    72.             }
    73.         }
    74.  
    75.         private static void ReceiveCallback(IAsyncResult ar)
    76.         {
    77.             UdpClient u = (UdpClient)((UdpState)(ar.AsyncState)).u;
    78.             IPEndPoint e = (IPEndPoint)((UdpState)(ar.AsyncState)).e;
    79.  
    80.             Byte[] receiveBytes = u.EndReceive(ar, ref e);
    81.             string receiveString = Encoding.ASCII.GetString(receiveBytes);
    82.  
    83.             Console.WriteLine("Received: {0}", receiveString);
    84.             messageReceived = true;
    85.         }
    86.  
    87.         struct UdpState
    88.         {
    89.             public UdpClient u;
    90.             public IPEndPoint e;
    91.         }
    92.  
    93.     }
    94. }
    The sending part is mostly 'made up', I assumed that the \xff and \x00 stuff was hex so I used Convert.ToChar to convert those hex numbers to characters and insert them before the actual command to send, just like the PHP source code does (at least: i think it does that, I may be completely wrong here as I have no clue how PHP works).

    The receiving part is straight from MSDN.

    I am trying to use it as such:
    csharp Code:
    1. Rcon r = new Rcon("173.199.111.167", "mypassword");
    2.             r.Connect();
    3.             r.SendCommand("teamstatus");
    "teamstatus" is supposed to be a valid command that should result in the server returning the players and their status (name, id, score, ping, etc).


    When I try to run this, nothing happens. The console displays "listening for messages" but nothing after that. I waited a few minutes but no response ever came.


    What am I doing wrong? As I said, I am completely new to this (both the PHP and to 'socket' stuff in general) so I really have no clue what I'm doing. At this point basically I'm trying to hack together a translation and I'm just looking to get A response, no matter what.

    Thanks!

  2. #2
    Software Carpenter dee-u's Avatar
    Join Date
    Feb 2005
    Location
    Pinas
    Posts
    11,127

    Re: PHP to C# - Sockets, or whatever, I dunno

    Why not post this in the PHP section? Penagate is fluent with both languages (php and C#), I believe he will be of help.
    Regards,


    As a gesture of gratitude please consider rating helpful posts. c",)

    Some stuffs: Mouse Hotkey | Compress file using SQL Server! | WPF - Rounded Combobox | WPF - Notify Icon and Balloon | NetVerser - a WPF chatting system

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width