Delphi STUN 服务器和客户端

· 组件

STUN(NAT 会话穿越实用工具,Session Traversal Utilities for NAT)是一种用于 IP 网络实时音视频的 IETF 协议。STUN 是一种服务器-客户端协议,STUN 服务器通常在 UDP 和 TCP 上运行并监听 3478 端口。

STUN 协议的主要目的是使 NAT 后面运行的设备能够发现其公网 IP 及 NAT 类型。

STUN 提供了一种在 NAT 后面的对等节点之间进行通信的机制。对等节点向 STUN 服务器发送请求,以了解自己的公网 IP 地址和端口。从客户端发送到服务器的绑定请求用于确定 NAT 分配的 IP 和端口绑定。STUN 客户端向 STUN 服务器发送绑定请求,服务器检查客户端使用的源 IP 和端口,并将此信息返回给客户端。

STUN 服务器

TsgcSTUNServer 是实现 STUN 协议的服务器,允许处理来自 STUN 客户端的绑定请求。

STUN 服务器可以配置为有或无身份验证,可以验证指纹属性、发送备用服务器等。

基本用法

通常 STUN 服务器在 UDP 3478 端口上运行且不需要身份验证,因此配置 STUN 服务器时,只需设置监听端口(默认 3478)并启动服务器即可。

服务器配置:

将属性 Active 设置为 True 以启动 STUN 服务器。

以下 Delphi 代码展示了如何启动新的 Delphi STUN 服务器:

oSTUN := TsgcSTUNServer.Create(nil);
oSTUN.Port := 3478;
oSTUN.Active := True;

长期凭据

通常 STUN 服务器配置为无需身份验证,因此任何 STUN 客户端都可以发送绑定请求并在无需身份验证的情况下期望获得服务器响应。

sgcWebSockets STUN 服务器支持长期凭据,因此您可以配置 TsgcSTUNServer 以仅允许包含长期凭据信息的绑定请求。

配置方法:访问 STUNOptions.Authorization 属性并启用它。

然后访问 LongTermCredentials 属性并启用它。默认情况下,此类型的授权已配置了 Realm 字符串和默认的 StaleNonce 值为 10 分钟(= 600 秒)。

以下 Delphi 代码展示了如何创建启用了长期凭据的 Delphi STUN 服务器:

oSTUN := TsgcSTUNServer.Create(nil);
oSTUN.Port := 3478;
oSTUN.STUNOptions.Authentication.Enabled := True;
oSTUN.STUNOptions.Authentication.LongTermCredentials.Enabled := True;
oSTUN.STUNOptions.Authentication.LongTermCredentials.Realm := 'sgcWebSockets';
oSTUN.STUNOptions.Authentication.LongTermCredentials.StaleNonce := 600;
oSTUN.Active := True;
procedure OnSTUNRequestAuthorization(Sender: TObject; const aRequest: TsgcSTUN_Message; const aUsername, aRealm: string; var Password: string);
begin
  if aUsername = 'my-user' then
    Password := 'my-password';
end;

STUN 客户端

TsgcSTUNClient 是实现 STUN 协议的客户端,允许向 STUN 服务器发送绑定请求。

该组件支持使用 UDPTCP 作为传输方式,在使用 UDP 作为传输时实现了重传机制,在短时间内未收到响应时会重新发送请求。

基本用法

通常 STUN 服务器在 UDP 3478 端口上运行且不需要身份验证,因此发送 STUN 绑定请求时,填写服务器属性以让客户端知道连接到哪里,并处理组件接收服务器响应的事件。

服务器配置:

调用方法 SendRequest,向 STUN 服务器发送绑定请求。

处理事件:

以下 Delphi 代码展示了如何创建新的 Delphi STUN 客户端并连接到 STUN 服务器:




oSTUN := TsgcSTUNClient.Create(nil);
oSTUN.Host := 'stun.sgcwebsockets.com';
oSTUN.Port := 3478;
oSTUN.SendRequest;
procedure OnSTUNResponseSuccess(Sender: TObject; const aMessage: TsgcSTUN_Message; const aBinding: TsgcSTUN_ResponseBinding);
begin
  DoLog('Remote IP: ' + aBinding.RemoteIP + '. Remote Port: ' + IntToStr(aBinding.RemotePort));
end;
procedure OnSTUNResponseError(Sender: TObject; const aMessage: TsgcSTUN_Message; const aError: TsgcSTUN_ResponseError);
begin
  DoLog('Error: ' + IntToStr(aError.Code) + ' ' + aError.Reason);
end;
});