ue4 如何获取端口号_UE4_使用WebSocket和Json(下)

2ada708682977f3b6e05dd559f3dd179.png

记录UE4中WebSocket和Json的使用方法(C++使用,蓝图没有的,想在蓝图用可以C++暴露方法给蓝图)。本文记录如何在UE4中使用Json来进行解析和写入。

内容:

  1. UE4 WebSocket Client
  2. Python WebSocket Server
  3. UE4 Json

UE4.25.3。项目github:

https://github.com/tiax615/UE4_Network​github.com

3. UE4 Json

在实际工作和学习中,Json是一个很常用的数据格式,不错的可读性,多语言的支持让Json广泛使用。

UE4中,Json使用也不复杂,百度一下能找到不错的参考。在第1步中实现了UE4WebSocketClient,在第2步中实现了PythonWebSocketServer,并接收了Client发送来的字符串,向Client发送了Json格式的字符串。第3步将记录如何在UE4中解析和生成Json。

3.1. 增加模块

和WebSockets模块一样,也需要在项目名.build.cs中新增Json模块

// Copyright Epic Games, Inc. All Rights Reserved.

using UnrealBuildTool;

public class UE4_Network : ModuleRules
{
	public UE4_Network(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
	
		PublicDependencyModuleNames.AddRange(new string[]
		{
			"Core", "CoreUObject", "Engine", "InputCore",
			"WebSockets", "Json"
		});

		PrivateDependencyModuleNames.AddRange(new string[] {  });

		// Uncomment if you are using Slate UI
		// PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
		
		// Uncomment if you are using online features
		// PrivateDependencyModuleNames.Add("OnlineSubsystem");

		// To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
	}
}

3.2. 修改Server

在第2步中,使用send_time()发送的Json中Value为一串string,还可以发送其他类型的数据,例如string/bool/number/array等。在Python的服务类中,新增下面这个方法send_something,发送各种类型的数据(一个包bool/int/float/string的array)。发送的something字符串,包含Topic和Data,其中Data中又包好Key和Value。

# 发送各类型数据
    def send_something(self):
        self._add_cmd('Unreal','Something',[False,66,123.4,"str"])

改写main函数,发送一次time,再发送一次something

def main():
    s=MyServer('127.0.0.1',23333)
    s.start_server()

    s.send_time()
    s.send_something()

运行Server,运行Client,结果如下。各自收发成功,但UE4也只当这是个字符串,没有做任何解析。

a42b1e0493a7e85ca0790afc21def4ef.png

f6b9a0d245ae3dc44a2c00577383f610.png

3.3. 解析Json

在.h中新增一个解析的方法JsonParse(),在OnMessage事件中调用这个解析:

// .h
protected:
    //...
    void JsonParse(const FString InMessage);

在JsonParse()的实现中,先定义RootObj和JsonReader,用JsonReader反序列化这个FJsonObject类型的对象。获取Topic和Key,根据Key来判断做何解析。如果Key是Time,就认为Value的值的字符串;如果Key是Something,就认为Value的值是Array,而Array的每个元素又可以解析成不同类型的数据。

// .cpp
void AActorWebSocket::OnMessage(const FString& Message)
{
	UE_LOG(LogTemp,Warning,TEXT("%s Message:%s"),*FString(__FUNCTION__),*Message);

	JsonParse(Message);
}

void AActorWebSocket::JsonParse(const FString InMessage)
{
	TSharedPtr<FJsonObject> RootObj=MakeShareable(new FJsonObject());
	TSharedRef<TJsonReader<>> JsonReader=TJsonReaderFactory<>::Create(InMessage);

	if(FJsonSerializer::Deserialize(JsonReader,RootObj)) // 通过JsonReader读取RootObj
	{
		FString Topic=RootObj->GetStringField("Topic"); // Topic
		UE_LOG(LogTemp,Warning,TEXT("%s Topic:%s"),*FString(__FUNCTION__),*Topic);
		
		TSharedPtr<FJsonObject> DataObj=MakeShareable(new FJsonObject());
		DataObj=RootObj->GetObjectField("Data"); // Data

		FString Key=DataObj->GetStringField("Key"); // Key
		UE_LOG(LogTemp,Warning,TEXT("%s Key:%s"),*FString(__FUNCTION__),*Key);

		if(Key.Equals("Time"))
		{
			FString Time=DataObj->GetStringField("Value"); // Value type is String
			UE_LOG(LogTemp,Warning,TEXT("%s Time:%s"),*FString(__FUNCTION__),*Time);
		}
		else if(Key.Equals("Something"))
		{
			TArray<TSharedPtr<FJsonValue>> Value=DataObj->GetArrayField("Value"); // Value type is Array

			bool BoolValue=Value[0]->AsBool();
			int IntValue=Value[1]->AsNumber();
			float FloatValue=Value[2]->AsNumber();
			FString StringValue=Value[3]->AsString();

			UE_LOG(LogTemp,Warning,TEXT("%s BoolValue:%d"),*FString(__FUNCTION__),BoolValue);
			UE_LOG(LogTemp,Warning,TEXT("%s IntValue:%d"),*FString(__FUNCTION__),IntValue);
			UE_LOG(LogTemp,Warning,TEXT("%s FloatValue:%f"),*FString(__FUNCTION__),FloatValue);
			UE_LOG(LogTemp,Warning,TEXT("%s StringValue:%s"),*FString(__FUNCTION__),*StringValue);
		}
	}
}

测试结果如下,UE4已经能分别解析Json中各类型的数据了。

9520a44c07d4b532322998e08f0c0b19.png

063bcc26e849b094286e2f3d2e84ab5c.png

3.4. 写入Json

现在UE4能接收到消息,并且作为Json来解析了。下面记录如何序列化写入Json,并发送出去给Server,让Server能够解析。

修改MySend(),初始化一个TSharedPtr<FJsonObject>类型的RootObj,给他新增几个字段。其中IsExecute字段的值是bool,Type字段的值是String,Value字段的值是JsonValue类型

void AActorWebSocket::MySend()
{
	TSharedPtr<FJsonObject> RootObj=MakeShareable(new FJsonObject);
	RootObj->SetBoolField("IsExecute",true);
	RootObj->SetStringField("Type","Test");
	TSharedPtr<FJsonValue> Value=MakeShareable(new FJsonValueNumber(GetGameTimeSinceCreation()));
	RootObj->SetField("Value",Value);

	FString JsonStr;
	TSharedRef<TJsonWriter<TCHAR>> JsonWriter=TJsonWriterFactory<TCHAR>::Create(&JsonStr);
	FJsonSerializer::Serialize(RootObj.ToSharedRef(),JsonWriter);
	
	if(Socket->IsConnected())
	{
		// Socket->Send(FString::SanitizeFloat(GetGameTimeSinceCreation()));
		Socket->Send(JsonStr);
	}

	UE_LOG(LogTemp,Warning,TEXT("%s Result:%s"),*FString(__FUNCTION__),*JsonStr);
}

修改PythonWebSocketServer中的接收方法,简单解析收到的消息:

# 接收处理
    async def __consumer(self,message):
        print('recv message: {0}'.format(message))
        self.__isExecute=True
        jsonContent=json.loads(message)
        self.__isExecute=jsonContent['IsExecute']
        self.__message_value=jsonContent['Value']
        print('IsExecute',jsonContent['IsExecute'])
        print('Type',jsonContent['Type'])
        print('Value',jsonContent['Value'])

测试,UE4成功发送Json,Python服务成功接收了Json并解析。

1af4125589c03a2fa6c0a2f58067f38f.png

acfff1009b8e01161e527d374de297a0.png

以上就实现了UE4中Json的解析和写入,代码还算简洁,但肯定有更优雅的方式。记录在此抛砖引玉~感谢阅读!

天剑行风:UE4_使用WebSocket和Json(上)​zhuanlan.zhihu.com
67756a9d97e7d5c64e3d6c16dc82e0cb.png

999. Ref

  1. UE4读写Json文件:https://blog.csdn.net/qq_39108291/article/details/102944396
  2. 项目github:https://github.com/tiax615/UE4_Network

本文原创,如需转载,请注明出处。欢迎讨论,谢谢!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值