【UE5】【C++】调用FWebSocketsModule写一个WebSockets子系统

有的工作需要自己写一个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子系统就写好了,下一篇文章我会添加一些稍微复杂一点的内容,比如多线程处理不同的请求,等我不犯懒的时候,嘿嘿。

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是一个使用libwebsockets-4.3.2C++ Websockets服务端的示例代码: ```c++ #include <libwebsockets.h> #include <iostream> #include <string> using namespace std; struct WebsocketServerData { int counter; }; static int callback_websockets(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { WebsocketServerData *server_data = (WebsocketServerData*)lws_context_user(lws_get_context(wsi)); switch (reason) { case LWS_CALLBACK_ESTABLISHED: cout << "Websocket client connection established" << endl; break; case LWS_CALLBACK_SERVER_WRITEABLE: { string message = "Hello, World! " + to_string(server_data->counter); unsigned char *buffer = new unsigned char[LWS_SEND_BUFFER_PRE_PADDING + message.length() + LWS_SEND_BUFFER_POST_PADDING]; memcpy(buffer + LWS_SEND_BUFFER_PRE_PADDING, message.c_str(), message.length()); lws_write(wsi, buffer + LWS_SEND_BUFFER_PRE_PADDING, message.length(), LWS_WRITE_TEXT); delete[] buffer; server_data->counter++; } break; case LWS_CALLBACK_RECEIVE: cout << "Received message from client: " << string((char*)in, len) << endl; lws_callback_on_writable_all_protocol(lws_get_context(wsi), lws_get_protocol(wsi)); break; case LWS_CALLBACK_CLOSED: cout << "Websocket connection closed" << endl; break; default: break; } return 0; } int main(int argc, char **argv) { struct lws_context_creation_info context_info; struct lws_protocols protocols[] = { { "websockets", callback_websockets, sizeof(WebsocketServerData), 0 }, { NULL, NULL, 0, 0 } }; WebsocketServerData server_data = { 0 }; int port = 8080; int exit_code = 0; memset(&context_info, 0, sizeof(context_info)); context_info.port = port; context_info.protocols = protocols; context_info.user = &server_data; struct lws_context *context = lws_create_context(&context_info); if (!context) { cerr << "Failed to create libwebsocket context" << endl; exit_code = 1; goto cleanup; } while (true) { lws_service(context, 50); } cleanup: if (context) { lws_context_destroy(context); } return exit_code; } ``` 这个示例代码创建了一个Websocket服务端,监听指定的端口,并且每收到一条客户端消息就回复一条消息。你可以根据你的需求调整服务端回复消息的内容和频率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值