I m developing an application that detects Source-based games running on the LAN. Following up on the specifications provided by Valve, I have it narrowed down to exactly what I want: making a UDP connection on port 27015, sending an A2S_INFO
query (0xFFFFFFFF followed by "TSource Engine Query") and parsing the binary reply.
This is the code I m working with:
Dim sIP As String = "192.168.0.154"
Dim nPort As Integer = 27015
Dim connectionMessage As String = "ÿÿÿÿTSource Engine Query" & Chr(0)
Dim endPoint As New IPEndPoint(IPAddress.Parse(sIP), nPort)
Dim client As Socket = New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)
client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 6000)
client.SendTo(Encoding.ASCII.GetBytes(connectionMessage), endPoint)
Console.WriteLine("Message sent to " & sIP & ":" & nPort & vbCrLf & connectionMessage)
Dim sBuffer(1400) As Byte
Try
client.ReceiveFrom(sBuffer, endPoint)
MsgBox(System.Text.Encoding.Unicode.GetString(sBuffer))
Catch ex As SocketException
MsgBox("Failed to receive response on " & sIP & ":" & nPort & ":" & vbCrLf & ex.Message)
End Try
I keep getting SocketError.TimedOut
exceptions, informing me:
Failed to receive response on 192.168.0.154:27015: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
I m fairly certain this is very close to the answer, because the following very simple PHP version works like a charm:
$ip = "192.168.0.154";
$port = 27015;
$fp = fsockopen("udp://".$ip,$port, $errno, $errstr);
socket_set_timeout($fp, 6);
$prefix = "xffxffxffxff";
$command = "TSource Engine Query";
$msg = "$prefix$command";
fputs($fp, $msg, strlen($msg));
$response = "";
do {
$response .= fgets($fp, 16);
$status = socket_get_status($fp);
} while ($status[ unread_bytes ]);
fclose ($fp);
echo $response;
This provides me with a reply in accordance with the specifications.
I m close, but something s amiss with my VB.NET code. What am I doing wrong?
The solution
The encoding type is not valid for transmitting binary data. I replaced the following:
Encoding.ASCII.GetBytes(connectionMessage)
with:
System.Text.Encoding.[Default].GetBytes(connectionMessage)
And it was instantly solved.
A more robust solution, suggested by "pub", might be to specify the code page (although I haven t tested this):
Encoding.GetEncoding("iso-8859-1").GetBytes(connectionMessage)