Query Mechanism/Csharp
From SA-MP Wiki
Source
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace Query
{
class RCONQuery
{
Socket qSocket;
IPAddress address;
int _port = 0;
string _password = null;
string[] results = new string[50];
int _count = 0;
public RCONQuery(string IP, int port, string password)
{
qSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
qSocket.SendTimeout = 5000;
qSocket.ReceiveTimeout = 5000;
try
{
address = Dns.GetHostAddresses(IP)[0];
}
catch
{
}
_port = port;
_password = password;
}
public bool Send(string command)
{
try
{
IPEndPoint endpoint = new IPEndPoint(address, _port);
using (MemoryStream stream = new MemoryStream())
{
using (BinaryWriter writer = new BinaryWriter(stream))
{
writer.Write("SAMP".ToCharArray());
string[] SplitIP = address.ToString().Split('.');
writer.Write(Convert.ToByte(Convert.ToInt32(SplitIP[0])));
writer.Write(Convert.ToByte(Convert.ToInt32(SplitIP[1])));
writer.Write(Convert.ToByte(Convert.ToInt32(SplitIP[2])));
writer.Write(Convert.ToByte(Convert.ToInt32(SplitIP[3])));
writer.Write((ushort)_port);
writer.Write('x');
writer.Write((ushort)_password.Length);
writer.Write(_password.ToCharArray());
writer.Write((ushort)command.Length);
writer.Write(command.ToCharArray());
}
if (qSocket.SendTo(stream.ToArray(), endpoint) > 0)
return true;
}
}
catch
{
return false;
}
return false;
}
public int Rceive()
{
try
{
for (int i = 0; i < results.GetLength(0); i++)
results.SetValue(null, i);
_count = 0;
EndPoint endpoint = new IPEndPoint(address, _port);
byte[] rBuffer = new byte[500];
int count = qSocket.ReceiveFrom(rBuffer, ref endpoint);
using (MemoryStream stream = new MemoryStream(rBuffer))
{
using (BinaryReader reader = new BinaryReader(stream))
{
if (stream.Length <= 11)
return _count;
reader.ReadBytes(11);
short len;
try
{
while ((len = reader.ReadInt16()) != 0)
results[_count++] = new string(reader.ReadChars(Convert.ToInt32(len)));
}
catch
{
return _count;
}
}
}
}
catch
{
return _count;
}
return _count;
}
public string[] Store(int count)
{
string[] rString = new string[count];
for (int i = 0; i < count && i < _count; i++)
rString[i] = results[i];
_count = 0;
return rString;
}
}
class Query
{
Socket qSocket;
IPAddress address;
int _port = 0;
string[] results;
int _count = 0;
DateTime[] timestamp = new DateTime[2];
public Query(string IP, int port)
{
qSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
qSocket.SendTimeout = 5000;
qSocket.ReceiveTimeout = 5000;
try
{
address = Dns.GetHostAddresses(IP)[0];
}
catch
{
}
_port = port;
}
public bool Send(char opcode)
{
try
{
EndPoint endpoint = new IPEndPoint(address, _port);
using (MemoryStream stream = new MemoryStream())
{
using (BinaryWriter writer = new BinaryWriter(stream))
{
writer.Write("SAMP".ToCharArray());
string[] SplitIP = address.ToString().Split('.');
writer.Write(Convert.ToByte(Convert.ToInt32(SplitIP[0])));
writer.Write(Convert.ToByte(Convert.ToInt32(SplitIP[1])));
writer.Write(Convert.ToByte(Convert.ToInt32(SplitIP[2])));
writer.Write(Convert.ToByte(Convert.ToInt32(SplitIP[3])));
writer.Write((ushort)_port);
writer.Write(opcode);
if (opcode == 'p')
writer.Write("8493".ToCharArray());
timestamp[0] = DateTime.Now;
}
if (qSocket.SendTo(stream.ToArray(), endpoint) > 0)
return true;
}
}
catch
{
return false;
}
return false;
}
public int Receive()
{
try
{
_count = 0;
EndPoint endpoint = new IPEndPoint(address, _port);
byte[] rBuffer = new byte[3402];
qSocket.ReceiveFrom(rBuffer, ref endpoint);
timestamp[1] = DateTime.Now;
using (MemoryStream stream = new MemoryStream(rBuffer))
{
using (BinaryReader reader = new BinaryReader(stream))
{
if (stream.Length <= 10)
return _count;
reader.ReadBytes(10);
switch (reader.ReadChar())
{
case 'i': // Information
{
results = new string[6];
results[_count++] = Convert.ToString(reader.ReadByte());
results[_count++] = Convert.ToString(reader.ReadInt16());
results[_count++] = Convert.ToString(reader.ReadInt16());
int hostnamelen = reader.ReadInt32();
results[_count++] = new string(reader.ReadChars(hostnamelen));
int gamemodelen = reader.ReadInt32();
results[_count++] = new string(reader.ReadChars(gamemodelen));
int languagelen = reader.ReadInt32();
results[_count++] = new string(reader.ReadChars(languagelen));
return _count;
}
case 'r': // Rules
{
int rulecount = reader.ReadInt16();
results = new string[rulecount * 2];
for (int i = 0; i < rulecount; i++)
{
int rulelen = reader.ReadByte();
results[_count++] = new string(reader.ReadChars(rulelen));
int valuelen = reader.ReadByte();
results[_count++] = new string(reader.ReadChars(valuelen));
}
return _count;
}
case 'c': // Client list
{
int playercount = reader.ReadInt16();
results = new string[playercount * 2];
for (int i = 0; i < playercount; i++)
{
int namelen = reader.ReadByte();
results[_count++] = new string(reader.ReadChars(namelen));
results[_count++] = Convert.ToString(reader.ReadInt32());
}
return _count;
}
case 'd': // Detailed player information
{
int playercount = reader.ReadInt16();
results = new string[playercount * 4];
for (int i = 0; i < playercount; i++)
{
results[_count++] = Convert.ToString(reader.ReadByte());
int namelen = reader.ReadByte();
results[_count++] = new string(reader.ReadChars(namelen));
results[_count++] = Convert.ToString(reader.ReadInt32());
results[_count++] = Convert.ToString(reader.ReadInt32());
}
return _count;
}
case 'p': // Ping
{
results = new string[1];
results[_count++] = timestamp[1].Subtract(timestamp[0]).Milliseconds.ToString();
return _count;
}
default:
return _count;
}
}
}
}
catch
{
return _count;
}
}
public string[] Store(int count)
{
string[] rString = new string[count];
for (int i = 0; i < count && i < _count; i++)
rString[i] = results[i];
_count = 0;
return rString;
}
}
}
Implementation
Just copy it into your code and you're good to go. To call it, use the methods like this:
Query.Query sQuery = new Query.Query("127.0.0.1", 7777);
sQuery.Send('i');
int count = sQuery.Receive();
string[] info = sQuery.Store(count);
/*
* Variable 'info' might now contain:
* Password Players Max. players Hostname Gamemode Language
* { "0", "12", "500", "Query test server", "LVDM", "English" }
*/
//-------------------------
Query.RCONQuery sQuery = new Query.RCONQuery("127.0.0.1", 7777, "changeme");
sQuery.Send("echo Hello from C#");
int count = sQuery.Receive();
string[] info = sQuery.Store(count);
/*
* Variable 'info' might now contain:
* { "Hello from C#" }
*/
