-
На буржуинском сайте, описан протокол для получения списка серверов:
https://developer.valvesoftware.com/wiki/Master_Server_Query_Protocol
В частности:
............
IP:Port
The first IP:Port you should send is "0.0.0.0:0"
From then on, IP:Port becomes the last IP:Port received in the master servers reply. This allows steam to then grab another list of more servers.
Terminate this with 0x00
............
End of IP address list
The full requested IP list may not fit in 1 x packet. Subsequent packets must be requested by using the last received IP address and Port as the 'seed' in the next request.
The end of the IP list is indicated by a received IP address of 0.0.0.0 Port:0.
............
Написал c инди -Request := '1' + #$FF + '0.0.0.0:0' + #$00 + '\appid\33930';
setLength(AnswerBytes, 4096);
IdUDPClient.Send(Request, IndyTextEncoding(1251));
I := IdUDPClient.ReceiveBuffer(AnswerBytes);
............
While RequestAddr <> '0.0.0.0:0' do
Begin
Request := '1' + #$FF + RequestAddr + #$00 + '\appid\33930';
setLength(AnswerBytes, 4096);
IdUDPClient.Send(Request, IndyTextEncoding(1251));
I := IdUDPClient.ReceiveBuffer(AnswerBytes);
setLength(AnswerBytes, I);
IF (Length(AnswerBytes) < 5) Then
Break;
RequestAddr := Get_Last_Addr(AnswerBytes);
For I := 0 to Length(AnswerBytes) - 1 do
AnswerString := AnswerString + AnsiChar(AnswerBytes[I]);
End;
............
Получаю ответ после первого запроса. Все правильно(проверял сервера, список рабочий).
Далее, если я правильно понял, -
В последнем пакете, должен прийти в конце ип 0.0.0.0 и порт 0, а до тех пор, необходимо слать запросы с указанием последнего ип+порта в пришедшем ответе.
В Get_Last_Addr получаю последний ИП+Порт, подставляю в запрос в цикле.. И приходит тот же ответ, что и на первый запрос.
Вот к примеру на php почти тоже самое - и все работает(вырезал именно формирование запроса).............
if ($serverIP == "0.0.0.0" AND $serverPort == "0")
{
echo("Sending new request to master ...\n");
$request = "1\xFF".$seedIP.":".$seedPort."\xFF\appid\33930";
............
Мож кто, что путного скажет? -
И еще, меня смущает немного вот это:
Note that whenever you open a new socket (and thus get a new random client port), the Master Server will always send you the first batch of IPs even if you pass a valid game server IP. Do not close your socket between packets. -
Try To (11.01.18 00:52) [2]IdUDPClient.Connect; // <- try to establish persistent connection before sending request
IdUDPClient.Send(Request, IndyTextEncoding(1251)); -
[2]
Ессесно, так и сделано -
IdUDPClient := TIdUDPClient.Create(nil);
IdUDPClient.BroadcastEnabled := True;
IdUDPClient.Host := Master_Host;
IdUDPClient.Port := Master_Port;
IdUDPClient.ReceiveTimeout := 23000;
Request := #$31 + #$FF + '0.0.0.0:0' + #$00 + '\appid\33930';
IdUDPClient.Active := True;
IdUDPClient.Connect;
setLength(AnswerBytes, 4096);
IdUDPClient.Send(Request, IndyTextEncoding(1251));
I := IdUDPClient.ReceiveBuffer(AnswerBytes); -
В цикл тоже добавил на всякий случай)
-
NoNameUltima (11.01.18 12:12) [5]Добавил
setLength(AnswerBytes, 0);
перед
setLength(AnswerBytes, 4096);
но все равно результата нема.. -
KilkennyCat © (12.01.18 12:59) [6]
> Добавил
> setLength(AnswerBytes, 0);
> перед
> setLength(AnswerBytes, 4096);
это надо в цикле делать, минимум 7 итераций -
> KilkennyCat © (12.01.18 12:59) [6]
сарказм?)
т.е. при таком написаннии:setLength(AnswerBytes, 4096);
Try
IdUDPClient.Send(Request, IndyTextEncoding(1251));
I := IdUDPClient.ReceiveBuffer(AnswerBytes);
Except
end;
внутри цикла, не может быть ситуации, - когда содержимое AnswerBytes останется прежним?
P.S. Вопрос, кстати снят - все порешал.
P.S.P.S. Ники в браузерах разные были. -
KilkennyCat © (13.01.18 01:09) [8]
> hf-trade © (13.01.18 00:05) [7]
> сарказм?)
да. хотя и бывают ситуации, когда на самом деле с виду одинаковые операции дают совершенно различный результат. но не здесь.
Здесь уместнее заполнить буфер нулями или фф, после setLength(AnswerBytes, 4096);
Но не уверен, непомню уже, мож, очистка автоматом ща делается. -
Как правильно распарсить ответ?
Function GET_SERVER_RULES(Host: String; Port: Word): AnsiString;
Var
IdUDPClient : TIdUDPClient;
Request : AnsiString;
Answer : TIdBytes;
Begin
Result := '';
Try
IdUDPClient := TIdUDPClient.Create(nil);
IdUDPClient.Host := Host;
IdUDPClient.Port := Port;
Request := #$FF + #$FF + #$FF + #$FF + #$56 + #$FF + #$FF + #$FF + #$FF;
setLength(Answer, 9);
For I := 0 to 9 do
Answer[I] := $FF;
IdUDPClient.Active := True;
IdUDPClient.Send(Request, IndyTextEncoding(1251));
IdUDPClient.ReceiveBuffer(Answer);
Request := #$FF + #$FF + #$FF + #$FF + #$56 + AnsiChar(Answer[5]) + AnsiChar(Answer[6]) + AnsiChar(Answer[7]) + AnsiChar(Answer[8]);
setLength(Answer, 4096);
For I := 0 to 4096 do
Answer[I] := $FF;
IdUDPClient.Send(Request, IndyTextEncoding(1251));
I := IdUDPClient.ReceiveBuffer(Answer);
setLength(Answer, I);
IdUDPClient.Free;
For I := 0 to HIGH(Answer) do
Result := Result + AnsiChar(Answer[I]);
Except
End;
End;
procedure TForm_Main.Button1Click(Sender: TObject);
Var
Server_Rules : AnsiString;
Begin
Server_Rules := GET_SERVER_RULES('110.232.24.106', 2303);
end;
https://developer.valvesoftware.com/wiki/Server_queries
A2S_RULES:
Response Format
Note:Responses to this query are usually multi-packeted.
Data Type Comment
Header byte Always equal to 'E' (0x45)
Rules short Number of rules in the response.
For every rule in "Rules" there is this chunk in the response:
Data Type Comment
Name string Name of the rule.
Value string Value of the rule. -
kilkennycat © (16.01.18 21:57) [10]
> For I := 0 to 4096 do
> Answer[I] := $FF;
FillChar, ZeroMemory...