有的工作需要自己写一个Websockets子系统,方便同事蓝图调用。
创建子系统
子系统分5种:EditorSubsystem、EngineSubsystem、GameInstanceSubsystem、LocalPlayerSubsystem和WorldSubsystem。它们之间主要的区别是生命周期的不同,这里我选择使用的是GameInstanceSubsystem。
在项目的C++文件夹里右键-新建C++类,然后选中我们要创建的类,点击下一步,然后修改成自己喜欢的类名即可。
WebsocketsSubsystem.h
.h文件的内容如下,主要是创建了5个基础函数:建立链接事件OnConnected(), 链接报错事件OnConnectionError(), 链接关闭事件OnClosed(),接收到信息时的事件OnMessage()以及 发送信息时的事件OnMessageSent()。
除此之外,还有两个在public层供外部调用的事件:OpenWebSockets()和CloseWebSockets(),这样外部可以直接通过这两个函数来开启和关闭WebSockets服务。
#pragma once
#include "CoreMinimal.h"
#include "IWebSocket.h"
#include "WebSocketsModule.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "WebSocketsSubsystem.generated.h"
/**
*
*/
UCLASS()
class YUANWEIERJI_API UWebSocketsSubsystem : public UGameInstanceSubsystem
{
GENERATED_BODY()
protected:
UWebSocketsSubsystem();
virtual ~UWebSocketsSubsystem() override;
void OnConnected();
void OnConnectionError(const FString& Error);
void OnClosed(int32 StatusCode, const FString& Reason, bool bWasClean);
void OnMessage(const FString& Message);
void OnMessageSent(const FString& MessageString);
public:
UFUNCTION(BlueprintCallable, Category = "WebSocketsSubsystem")
void OpenWebSockets(const FString ServerURL="ws://127.0.0.1:8443/admin/ws", const FString Token="12345678");
UFUNCTION(BlueprintCallable, Category = "WebSocketsSubsystem")
void CloseWebSockets() const;
private:
const FString ServerProtocol = "ws";
TSharedPtr<IWebSocket> Socket = nullptr;
};
WebsocketsSubsystem.cpp
cpp里的大部分函数代码都比较简单,只是在log里print一下文字,稍微复杂一点的就是OpenWebSockets()这个函数,这里的代码包含了给声明好的IWebSocket实例Socket初始化赋值,以及绑定OnConnected等5个函数到Socket上。
#include "WebSocketsSubsystem.h"
UWebSocketsSubsystem::UWebSocketsSubsystem()
{
}
UWebSocketsSubsystem::~UWebSocketsSubsystem() {
if (Socket != nullptr && Socket->IsConnected()) {
Socket->Close();
}
}
void UWebSocketsSubsystem::OnConnected()
{
UE_LOG(LogTemp,Warning,TEXT("开始接收数据"));
}
void UWebSocketsSubsystem::OnConnectionError(const FString& Error)
{
UE_LOG(LogTemp,Warning,TEXT("接收数据出错,Error:%s"),*Error);
}
void UWebSocketsSubsystem::OnClosed(int32 StatusCode, const FString& Reason, bool bWasClean)
{
UE_LOG(LogTemp,Warning,TEXT("接收数据关闭,StatusCode:%d Reason:%s bWasClean:%d"),StatusCode,*Reason,bWasClean);
}
void UWebSocketsSubsystem::OnMessage(const FString& Message)
{
UE_LOG(LogTemp,Warning,TEXT("接收信息 Message:%s"),*Message);
}
void UWebSocketsSubsystem::OnMessageSent(const FString& MessageString)
{
UE_LOG(LogTemp,Warning,TEXT("信息已发送 MessageString:%s"),*MessageString);
}
void UWebSocketsSubsystem::OpenWebSockets(const FString ServerURL, const FString Token)
{
const FString Params = "?token=" + Token;
Socket = FWebSocketsModule::Get().CreateWebSocket(ServerURL+Params,ServerProtocol);
Socket->OnConnected().AddUObject(this,&UWebSocketsSubsystem::OnConnected);
Socket->OnConnectionError().AddUObject(this,&UWebSocketsSubsystem::OnConnectionError);
Socket->OnClosed().AddUObject(this,&UWebSocketsSubsystem::OnClosed);
Socket->OnMessage().AddUObject(this,&UWebSocketsSubsystem::OnMessage);
Socket->OnMessageSent().AddUObject(this,&UWebSocketsSubsystem::OnMessageSent);
Socket->Connect();
}
void UWebSocketsSubsystem::CloseWebSockets() const
{
Socket->Close();
}
结语
这样一个简单又基础的WebSockets子系统就写好了,下一篇文章我会添加一些稍微复杂一点的内容,比如多线程处理不同的请求,等我不犯懒的时候,嘿嘿。