C++
添加模块
打开你的源码构建配置文件 (<ProjectName>.Build.cs),并将模块依赖添加到编译指令列表中:
PublicDependencyModuleNames.Add("BlueprintWebSocket");
引入头文件
通过将封装头文件放入你的类文件中,公开接口类型:
#include "BlueprintWebSocketWrapper.h"
创建新的 WebSocket
使用插件工厂方法实例化堆分配:
UBlueprintWebSocket* const WebSocket = UBlueprintWebSocket::CreateWebSocket();
配置 WebSocket
在调用连接握手例程之前,修改传输元数据结构与身份验证标头:
// 将提供的 map 与当前标头列表合并。
WebSocket->SetHeaders(const TMap<FString, FString> & InHeaders);
// 向标头列表添加一对 Key / Value。
WebSocket->AddHeader(const FString & Header, const FString & Value);
// 从标头列表中移除该标头
WebSocket->RemoveHeader(const FString & HeaderToRemove);
使用回调监听事件
将函数目标绑定到异步委托,安全地接收网络响应状态变更:
| 事件名称
| 签名
| 描述
|
OnConnectedEvent
| void Func()
| 当我们成功连接到 WebSocket 服务器时调用。
|
OnConnectionErrorEvent
| void Func(const FString & Error)
| 当我们无法连接到 WebSocket 服务器时调用。
|
OnCloseEvent
| void Func(int64 StatusCode, const FString & Reason, bool bWasClean)
| 当与服务器的连接已关闭时调用。
|
OnMessageEvent
| void Func(const FString & Message)
| 当我们收到字符串消息时调用。
|
OnRawMessageEvent
| void Func(const TArray<uint8> & Data, int32 BytesRemaining)
| 当我们收到二进制消息时调用。
|
OnMessageSentEvent
| void Func(const FString & Message)
| 在我们发送消息后立即调用。
|
由于这些钩子使用 Dynamic Multicast Delegates,任何绑定的监听函数都必须带有 UFUNCTION() 修饰宏,才能在引擎调用栈中保持可见:
UCLASS()
class MYGAME_API UMyClass : public UObject
{
GENERATED_BODY()
public:
// 我们用来绑定事件的函数
void BindEvents();
private:
// 回调
UFUNCTION() void OnConnected();
UFUNCTION() void OnConnectionError(const FString & Error);
UFUNCTION() void OnClosed(int64 StatusCode, const FString & Reason, bool bWasClean);
UFUNCTION() void OnMessage(const FString & Message);
UFUNCTION() void OnRawMessage(const TArray<uint8> & Data, int32 BytesRemaining);
UFUNCTION() void OnMessageSent(const FString & Message);
private:
UPROPERTY()
UBlueprintWebSocket* WebSocket;
};
void UMyClass::BindEvents()
{
// 绑定事件,使我们的函数在事件触发时被调用。
WebSocket->OnConnectedEvent .AddDynamic(this, &UMyClass::OnConnected);
WebSocket->OnConnectionErrorEvent.AddDynamic(this, &UMyClass::OnConnectionError);
WebSocket->OnCloseEvent .AddDynamic(this, &UMyClass::OnClosed);
WebSocket->OnMessageEvent .AddDynamic(this, &UMyClass::OnMessage);
WebSocket->OnRawMessageEvent .AddDynamic(this, &UMyClass::OnRawMessage);
WebSocket->OnMessageSentEvent .AddDynamic(this, &UMyClass::OnMessageSent);
}
连接到 WebSocket 服务器
将显式的端点 URI 与通信协议子字符串直接传入连接处理循环:
WebSocket->Connect(TEXT("wss://stream.binance.com:9443/ws/btcusdt@trade"), TEXT("ws"));
通过功能状态检查器内联查询状态帧:
if (WebSocket->IsConnected())
{
// 我们已连接。
}
else
{
// 我们未连接。
}
注意: 你不应依赖 IsConnected() 来处理连接,而应依赖 OnConnectedEvent 回调。
发送消息
使用结构化字符串或直接内存缓冲区向下游传输信息:
void SendMessage(const FString & Message):用于传递文本/JSON 数据格式。
void SendRawMessage(const TArray<uint8> & Message, const bool bIsBinary):用于推送压缩结构或资源文件。
实现示例:
// 我们想要发送的数据,你可以通过程序化方式获取。
const FString StringMessage = TEXT("Hello Server");
const TArray<uint8> BinaryMessage = { 0, 1, 2, 3, 4, 5 };
// 通过我们的 WebSocket 发送。
WebSocket->SendMessage (StringMessage);
WebSocket->SendRawMessage(BinaryMessage);
完整示例
MyClass.h
#pragma once
#include "CoreMinimal.h"
#include "MyClass.generated.h"
class UBlueprintWebSocket;
/**
* 我们使用 WebSocket 的自定义类。
**/
UCLASS()
class MYGAME_API UMyClass : public UObject
{
GENERATED_BODY()
public:
void InitializeAndConnectSocket();
private:
UFUNCTION()
void OnConnected();
UFUNCTION()
void OnConnectionError(const FString & Error);
UFUNCTION()
void OnClosed(int64 StatusCode, const FString & Reason, bool bWasClean);
UFUNCTION()
void OnMessage(const FString & Message);
UFUNCTION()
void OnRawMessage(const TArray<uint8> & Data, int32 BytesRemaining);
UFUNCTION()
void OnMessageSent(const FString & Message);
private:
UPROPERTY()
UBlueprintWebSocket* WebSocket;
};
MyClass.cpp
#include "MyClass.h"
#include "BlueprintWebSocketWrapper.h"
void UMyClass::InitializeAndConnectSocket()
{
WebSocket = UBlueprintWebSocket::CreateWebSocket();
WebSocket->OnConnectedEvent .AddDynamic(this, &UMyClass::OnConnected);
WebSocket->OnConnectionErrorEvent.AddDynamic(this, &UMyClass::OnConnectionError);
WebSocket->OnCloseEvent .AddDynamic(this, &UMyClass::OnClosed);
WebSocket->OnMessageEvent .AddDynamic(this, &UMyClass::OnMessage);
WebSocket->OnRawMessageEvent .AddDynamic(this, &UMyClass::OnRawMessage);
WebSocket->OnMessageSentEvent .AddDynamic(this, &UMyClass::OnMessageSent);
WebSocket->AddHeader(TEXT("SomeHeader"), TEXT("SomeValue"));
WebSocket->Connect(TEXT("wss://stream.binance.com:9443/ws/btcusdt@trade"), TEXT("ws"));
}
void UMyClass::OnConnected()
{
UE_LOG(LogTemp, Log, TEXT("We are connected!"));
WebSocket->SendMessage(TEXT("Hello Server!"));
}
void UMyClass::OnConnectionError(const FString & Error)
{
UE_LOG(LogTemp, Error, TEXT("Failed to connect: %s."), *Error);
}
void UMyClass::OnClosed(int64 StatusCode, const FString & Reason, bool bWasClean)
{
UE_LOG(LogTemp, Warning, TEXT("Connection closed: %d:%s. Clean: %d"), StatusCode, *Reason, bWasClean);
}
void UMyClass::OnMessage(const FString & Message)
{
UE_LOG(LogTemp, Log, TEXT("New message: %s"), *Message);
}
void UMyClass::OnRawMessage(const TArray<uint8> & Data, int32 BytesRemaining)
{
UE_LOG(LogTemp, Log, TEXT("New binary message: %d bytes and %d bytes remaining."), Data.Num(), BytesRemaining);
}
void UMyClass::OnMessageSent(const FString & Message)
{
UE_LOG(LogTemp, Log, TEXT("We just sent %s to the server."), *Message);
}