【UE5】UE5与Python Socket通信中文数据接收不全

这篇具有很好参考价值的文章主要介绍了【UE5】UE5与Python Socket通信中文数据接收不全。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

最近在使用UE的Socket模块与Python服务器进行通信时遇到了一些坑,特此记录一下。

先来复现一下问题,这里只截取关键代码。

UE端:

bool ASoc::SendMsg(const FString& Msg)
{
	TSharedRef<FInternetAddr> TargetAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
	FString Serialized = Msg;
	bool bSend;
	TCHAR* SeriallizedChar = Serialized.GetCharArray().GetData();
	int32 Size = FCString::Strlen(SeriallizedChar) + 1;
	int32 Sent = 0;
	bSend = SocClient->SendTo((uint8*)TCHAR_TO_UTF8(SeriallizedChar),Size,Sent,*TargetAddr);
	if(bSend)
	{
		UE_LOG(LOGNLPFORUE,Log,TEXT("[To LTP | %d]: %s"),Size,*Msg);
	}
	else
	{
		UE_LOG(LOGNLPFORUE,Log,TEXT("Failed to send Msg to tlp"));
	}
	return bSend;
}

Python端:

def socrecv():
    global data,conn,addr,soc
    while True:
        data = str(conn.recv(recvbuff),'utf-8','ignore')
        print('[recv msg from ue |',sys.getsizeof(data),']: ',repr(data))

def soclisten():
    global soc,bind,conn,addr,recvthread
    soc=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    soc.bind((ip,port))
    soc.listen(5)
    print('server listen...')
    bind = True
    while True:
        conn,addr = soc.accept()
        print(addr,'已接入')
        recvthread = Thread(target=socrecv)
        recvthread.setDaemon(True)
        recvthread.start()   

soclisten()

运行结果:

UE端发送的数据:

LOGNLPFORUE: [To LTP | 45]: {"cmd":"ltp","type":"cws","data":"他叫汤姆去拿外衣"}
LOGNLPFORUE: [To LTP | 102]: {"cmd":"ltp","type":"cws","data":"He told Tom to get the coat, but Tom brought a piece of underwear"}

Python端接收到数据:

[recv msg from ue | 148 ]:  '{"cmd":"ltp","type":"cws","data":"他叫汤'
[recv msg from ue | 151 ]:  '{"cmd":"ltp","type":"cws","data":"He told Tom to get the coat, but Tom brought a piece of underwear"}\x00'

可以看到数据容量并没有超出缓存上限,且Python端接收的数据都有做utf-8的编码转换,但依旧出现了中文数据接收不全,容量更大的英文数据反而没问题。

问题出在了UE端的FSocket::SendTo函数,SendTo函数的定义:

bool FSocket::SendTo(const uint8* Data, int32 Count, int32& BytesSent, const FInternetAddr& Destination)

Data就是我们要发送的字节数据,Count数据的大小,BytesSent记录的是数据的发送进度,Destination是要发送数据的地址。

问题就出在Count的值上,可以看到在上面的代码中我们是直接计算的FString的长度,然后以这个长度作为发送的数据大小,在纯英文的数据中这没有任何问题,但在中文数据中,由于中文编码的特殊性,FString应该有做特殊的编码处理,导致直接计算FString的长度作为发送数据的字节大小其实是小于真实数据大小的,这就导致在UE端发送中文数据时就没有发送完整到数据,所以Python端接收到数据就出现数据不全的问题。

既然知道原因了,接下来就可以解决了。那么我们就需要去找一个计算FString中文数据真实字节数的算法来计算SenTo要发送字节数据大小。

在网上我也没找到相关的算法代码,于是就去请教了一位大佬,大佬给了我一份算法代码:

int32 ASoc::CalcUtf0NumFromString(const FString& Str)
{
	int32 result = 0; 
	for (int i = 0; i < Str.Len(); i++)
	{
		if (Str[i] <= 0x7f)
			result = result + 1;
		else if (Str[i] > 0x7f && Str[i] <= 0x07ff)
			result = result + 2;
		else if (Str[i] > 0x07ff && Str[i] <= 0xffff)
			result = result + 3;
		else
			result = result + 4;
	}
	return result + 1;
}

没有去深究FString的中英文编码,代码我是没看明白的,使用这个算法计算数据的字节大小,就能计算出正确的大小。

然后UE端的代码将int32 Size = FCString::Strlen(SeriallizedChar) + 1;换成int32 Size = CalcUtf0NumFromString(SeriallizedChar);,问题就解决了。文章来源地址https://www.toymoban.com/news/detail-633759.html

到了这里,关于【UE5】UE5与Python Socket通信中文数据接收不全的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • UE5学习笔记(一)——界面功能梳理&第一天知识点记录

    学习UE5的第一步,是软件安装。 默认是安装好的,由于安装没有太多技术含量,所以就没有专门做记录。 这里有个注意点,虚幻引擎是整合在Epic games launcher中的,也就是说开发引擎内嵌在游戏平台上,打个比方,就是如果你要下unity你必须先下一个steam的感觉。 当然,在完

    2024年02月04日
    浏览(51)
  • JAVA Socket实现实时接收TCP消息,让你的服务端通信更高效!

    本文主要介绍如何利用socket实现实时接收服务端发送的TCP消息。 目录 一、需要掌握 二、程序源码 三、运行演示 网络调试助手下载:https://www.aliyundrive.com/s/6Y8L7Wv5sT6 网络通信协议的理解:JAVA socket是基于TCP/IP协议实现的,需要对TCP/IP协议有一定的了解,包括TCP连接的建立、数

    2024年02月11日
    浏览(42)
  • 利用python进行TCP通信接收数据进行处理,使用队列来存放接收的数据

            在上面的程序中,我们创建了一个队列 data_queue 来存放接收到的数据,并使用Python的socket模块创建了一个TCP服务器套接字 server_socket 。当有客户端连接请求时,程序会创建一个新线程来处理客户端请求,并在处理函数 handle_client 中将接收到的数据放入队列中。  

    2024年02月13日
    浏览(42)
  • unity + python socket通信,自定义数据包

    unity和python相互之间通过socket通信来发送自定义数据包是一个利用unity构建场景和通过python来做数据处理的方式,能够有效的利用两种不同语言的优势。 我已经将对应的操作封装为对应的一个模块,SocketTools.cs,我们先来看一下具体的代码用法(这段代码是一个简单的将unity主

    2024年02月08日
    浏览(51)
  • 在UE5编辑器环境中使用Python

    UE有很多Python方案,本文所讲述的Python为UE5官方内嵌版本方案,并且只能在编辑器环境下使用,使用该功能可以编写编辑器下的辅助工具,提升开发效率。 讲一讲UE5中调用Python的几种方式,首先是控制台下调用Python,将控制台的CMD图标换成Python,即可输入并执行Python语句:

    2024年02月11日
    浏览(50)
  • 【网络】socket——预备知识 | 套接字 | UDP网络通信

    🐱作者:一只大喵咪1201 🐱专栏:《网络》 🔥格言: 你只管努力,剩下的交给时间! 在前面本喵对网络的整体轮廓做了一个大概的介绍,比如分层,协议等等内容,现在我们直接进入socket(套接字)编程,先来感受到网络编程。 我们知道,在网络通信中,存在两套地址,一

    2024年02月13日
    浏览(54)
  • 【UE5:CesiumForUnreal】——3DTiles数据属性查询和单体高亮

    目录 0.1 效果展示 0.2 实现步骤 1  数据准备   2  属性查询 2.1 射线检测  2.2 获取FeatureID 2.3 属性查询 2.4  属性显示 3 单体高亮 3.1 构建材质参数集 3.2 材质参数设置 3.3 添加Cesium Encode Metadata插件 3.4 从纹理中取出特定FeatureId属性信息 3.5 创建材质图层 3.6 创建混合材质图层

    2024年02月11日
    浏览(39)
  • UE5 C++自定义Http节点获得Header数据

    一、新建C++文件   选择All Classes,选择父类BlueprintFunctionLibrary,命名为SendHttpRequest。 添加Http支持 代理回调的参数使用DECLARE_DYNAMIC_DELEGATE_TwoParam定义,第一参数是代理类型,后面是参数1类型,参数1,参数2类型,参数2。 代理通过UPROPERTY声明 UFUNCTION的BlueprintCallable是定义一个

    2024年02月04日
    浏览(39)
  • 【STM32笔记】HAL库低功耗STOP停止模式的串口唤醒(解决进入以后立马唤醒、串口唤醒和回调无法一起使用、接收数据不全的问题)

    【STM32】HAL库低功耗STOP停止模式的串口唤醒(解决进入以后立马唤醒、串口唤醒和回调无法一起使用、接收数据不全、首字节错误的问题) 【STM32笔记】低功耗模式配置及避坑汇总 前文: blog.csdn.net/weixin_53403301/article/details/128216064 【STM32笔记】HAL库低功耗模式配置(ADC唤醒无

    2024年02月14日
    浏览(39)
  • C#知识点-13(进程、多线程、使用Socket实现服务器与客户端通信)

    进程 定义:每一个正在运行的应用程序,都是一个进程  进程不等于正在运行的应用程序。而是为应用程序的运行构建一个运行环境 多线程 这段代码在执行完成之前,程序会被卡死(不能操作程序,包括关闭窗口)。因为我们程序在做一些耗时操作的时候,如果主线程去执

    2024年02月22日
    浏览(93)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包