Я разрабатываю приложение, которое обнаруживает исходные игры, работающие в локальной сети.Следуя спецификациям , предоставленным Valve , я сузил его до именно того, что я хочу: сделать UDP-соединение на порту 27015, отправив запрос A2S_INFO
(0xFFFFFFFF, за которым следует "TSource Engine Query")и синтаксический анализ двоичного ответа.
Это код, с которым я работаю:
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
Я получаю SocketError.TimedOut
исключений, сообщая мне:
Не удалось получить ответ на 192.168.0.154:27015: Попытка подключения не удалась, поскольку подключенная сторона не ответила должным образом через некоторое время, или не удалось установить соединение, так как подключенный хост не смог ответить
Я вполне уверен, что это очень близко к ответу, потому что следующая очень простая версия PHP работает как шарм:
$ip = "192.168.0.154";
$port = 27015;
$fp = fsockopen("udp://".$ip,$port, $errno, $errstr);
socket_set_timeout($fp, 6);
$prefix = "\xff\xff\xff\xff";
$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;
Это дает мне ответ в соответствии со спецификациями.
Я близок, но что-то не так с моим кодом VB.NET.Что я делаю не так?
Решение
Тип кодировки недопустим для передачи двоичных данных.Я заменил следующее:
Encoding.ASCII.GetBytes(connectionMessage)
на:
System.Text.Encoding.[Default].GetBytes(connectionMessage)
И это было немедленно решено.
Более надежное решение, предложенное "pub", может бытьуказать кодовую страницу (хотя я не проверял это):
Encoding.GetEncoding("iso-8859-1").GetBytes(connectionMessage)