【发布时间】:2010-12-14 20:53:04
【问题描述】:
我正在开发一个应用程序来检测在 LAN 上运行的基于源的游戏。跟进specifications provided by Valve,我将其缩小到我想要的范围:在端口 27015 上建立 UDP 连接,发送A2S_INFO 查询(0xFFFFFFFF 后跟“TSource 引擎查询”)并解析二进制回复。
这是我正在使用的代码:
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)
【问题讨论】: