我正在尝试使用Delphi XE4按照here所述将A2A_PING UDP数据包发送到HLDS服务器。但是,我没有得到任何回应。当我使用Packet Sender进行测试时,我在Packet Sender中得到了预期的响应。
我要做的是创建一个服务器监视器,在其UDP端口上发送ping。因此,我的应用程序将始终使用其本地IP在服务器上本地运行。服务器的UDP端口是27015。
我要发送的UDP数据包是:
十六进制:FF FF FF FF 69
等效字符串:ÿÿÿÿi
以下是我试过的内容:
unit uFrmMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ShellAPI, IdUDPServer, IdBaseComponent, IdComponent,
IdUDPBase, IdUDPClient, IdSocketHandle, IdGlobal;
type
TfrmMain = class(TForm)
ListBox1: TListBox;
btnSendMessage: TButton;
btnInitialize: TButton;
procedure btnSendMessageClick(Sender: TObject);
procedure IdUDPServer1UDPRead(AThread: TIdUDPListenerThread; const AData: TIdBytes; ABinding: TIdSocketHandle);
procedure btnInitializeClick(Sender: TObject);
private
function String2Hex(const Buffer: Ansistring): string;
procedure Initialize;
public
{ Public declarations }
end;
const
Host = '172.30.0.96';
TargetPort = 27015;
LocalListenPort = 47001;
MessageToSend = 'ÿÿÿÿi'; // need to send: FF FF FF FF 69
var
frmMain: TfrmMain;
udpServer: TIdUDPServer;
udpClient: TIdUDPClient;
implementation
{$R *.dfm}
procedure TfrmMain.Initialize;
var
binding: TIdSocketHandle;
begin
// Setup UDP Server
udpServer := TIdUDPServer.Create(frmMain);
udpServer.Active := false;
binding := udpServer.Bindings.Add;
Binding.IP := Host; // local host ip
binding.Port := LocalListenPort; // Listen for incoming messages on 47001
udpServer.OnUDPRead := IdUDPServer1UDPRead;
udpServer.Active := true;
// Setup UDP client
udpClient := TIdUDPClient.Create(frmMain);
udpClient.Host := Host; // Local host ip
udpClient.Port := TargetPort; // Send messages to 27015
udpClient.Active := true;
end;
procedure TfrmMain.btnInitializeClick(Sender: TObject);
begin
Initialize;
end;
procedure TfrmMain.btnSendMessageClick(Sender: TObject);
begin
udpClient.SendBuffer(Host, TargetPort, ToBytes(MessageToSend));
end;
procedure TfrmMain.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread; const AData: TIdBytes; ABinding: TIdSocketHandle);
begin
ListBox1.Items.Add(BytesToString(AData));
end;
function TfrmMain.String2Hex(const Buffer: Ansistring): string;
begin
SetLength(result, 2*Length(Buffer));
BinToHex(@Buffer[1], PWideChar(@result[1]), Length(Buffer));
end;
end.
更新根据Remy的建议,我也试过了这个:
unit uFrmMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ShellAPI, IdUDPServer, IdBaseComponent, IdComponent,
IdUDPBase, IdUDPClient, IdSocketHandle, IdGlobal;
type
TfrmMain = class(TForm)
ListBox1: TListBox;
btnSendMessage: TButton;
btnInitialize: TButton;
procedure btnSendMessageClick(Sender: TObject);
procedure IdUDPServer1UDPRead(AThread: TIdUDPListenerThread; const AData: TIdBytes; ABinding: TIdSocketHandle);
procedure btnInitializeClick(Sender: TObject);
private
function String2Hex(const Buffer: Ansistring): string;
procedure Initialize;
public
{ Public declarations }
end;
const
// Host = '172.30.0.96';
Host = '192.168.190.1';
TargetPort = 27015;
LocalListenPort = 47001;
var
frmMain: TfrmMain;
udpServer: TIdUDPServer;
// udpClient: TIdUDPClient;
binding: TIdSocketHandle;
implementation
{$R *.dfm}
procedure TfrmMain.Initialize;
var
bytes_received: integer;
begin
// Setup UDP Server
udpServer := TIdUDPServer.Create(frmMain);
udpServer.Active := false;
udpServer.DefaultPort := 0;
binding := udpServer.Bindings.Add;
Binding.IP := Host; // local host ip
binding.Port := LocalListenPort; // Listen for incoming messages on 47001
udpServer.OnUDPRead := IdUDPServer1UDPRead;
udpServer.Active := true;
// Setup UDP client
// udpClient := TIdUDPClient.Create(frmMain);
// udpClient.Host := Host; // Local host ip
// udpClient.Port := TargetPort; // Send messages to 27015
// udpClient.BoundIP := Host;
// udpClient.BoundPort := LocalListenPort;
// udpClient.ReceiveTimeout := 2000;
// udpClient.Active := true;
end;
procedure TfrmMain.btnInitializeClick(Sender: TObject);
begin
Initialize;
end;
procedure TfrmMain.btnSendMessageClick(Sender: TObject);
var
MessageToSend: TIdBytes;
begin
SetLength(MessageToSend, 5);
MessageToSend[0] := $FF;
MessageToSend[1] := $FF;
MessageToSend[2] := $FF;
MessageToSend[3] := $FF;
MessageToSend[4] := $69;
// udpClient.SendBuffer(Host, TargetPort, RawToBytes(MessageToSend, SizeOf(MessageToSend)));
binding.SendTo(Host, TargetPort, RawToBytes(MessageToSend, SizeOf(MessageToSend)));
end;
procedure TfrmMain.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread; const AData: TIdBytes; ABinding: TIdSocketHandle);
begin
ListBox1.Items.Add(ToHex(AData));
end;
end.
由于Packet Sender工作正常,我必须遗漏一些非常明显的东西。 非常感谢任何帮助。
答案 0 :(得分:3)
您不应该为消息使用字符串(如果您使用的是Delphi 2009+,尤其是Unicode字符串)。您使用的协议本质上是二进制的,而不是文本的。您需要使用原始字节进行操作,例如:
const
MessageToSend: array[0..4] of Byte = ($FF, $FF, $FF, $FF, $69);
procedure TfrmMain.btnSendMessageClick(Sender: TObject);
begin
udpClient.SendBuffer(Host, TargetPort, RawToBytes(MessageToSend, SizeOf(MessageToSend));
end;
{
Alternatively:
procedure TfrmMain.btnSendMessageClick(Sender: TObject);
var
MessageToSend: TIdBytes;
begin
SetLength(MessageToSend, 5);
MessageToSend[0] := $FF;
MessageToSend[1] := $FF;
MessageToSend[2] := $FF;
MessageToSend[3] := $FF;
MessageToSend[4] := $69;
udpClient.SendBuffer(Host, TargetPort, MessageToSend);
end;
}
procedure TfrmMain.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread; const AData: TIdBytes; ABinding: TIdSocketHandle);
begin
ListBox1.Items.Add(ToHex(AData));
end;