【UE5】如何开发安卓项目的udp客户端

发布于:2025-06-21 ⋅ 阅读:(16) ⋅ 点赞:(0)

在这里插入图片描述

1关于如何打包安卓项目这里就不赘述了
2代码举例。最重要的就是这两句`

#if PLATFORM_ANDROID
#endif

#if PLATFORM_WINDOWS
#endif

全部代码如下:
Button_Sheng.h:

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"

#include "Components/Button.h"
#include "Components/TextBlock.h"

#include "Button_Sheng.generated.h"
#if PLATFORM_ANDROID
#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <unistd.h>  
#include <arpa/inet.h>  
#include <sys/socket.h>  
#include <netinet/in.h>  
#include <pthread.h>  
#endif

/**
 * 
 */
UCLASS()
class CCEC_CLIENT_0113_API UButton_Sheng : public UUserWidget
{
	GENERATED_BODY()

public:
    // 声明按钮和文本块
    UPROPERTY(meta = (BindWidget))
    UButton* MyButton;

    UPROPERTY(meta = (BindWidget))
    UTextBlock* MyTextBlock;

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Custom")
    int Code;

    
    // 移植过来的函数声明
    UFUNCTION(BlueprintCallable, Category = "aaaaaa")
    void Sheng(FString Message);
protected:
    // 构造函数
    virtual void NativeConstruct() override;


public:
    // 动态创建 Widget 的函数
    UFUNCTION(BlueprintCallable, Category = "Widget")
    void CreateDynamicWidget(int32 WidgetID);

    // 动态创建 Widget 的函数(基于 FString)
    UFUNCTION(BlueprintCallable, Category = "Widget")
    void CreateDynamicWidgetByName(const FString& WidgetName);

protected:
    // 父容器,用于存放动态创建的 Widget
    //UPROPERTY(meta = (BindWidget))
    //class UPanelWidget* ParentContainer;
};

Button_Sheng.cpp:

#include "Button_Sheng.h"
#include "Components/WidgetComponent.h"
#include <iostream>  

#include "Blueprint/WidgetTree.h"
#include "Components/PanelWidget.h"
#include "UObject/ConstructorHelpers.h"

#if PLATFORM_ANDROID
#define BROADCAST_PORT 8888  
#define BROADCAST_PORT2 8889  
#define BROADCAST_PORT3 8887 
#define BROADCAST_MESSAGE1 "1" 
#define BROADCAST_MESSAGE2 "2" 
#define BROADCAST_MESSAGE3 "3" 
#define BROADCAST_MESSAGE42 "42"

void* send_broadcast13(void* arg) {
    int sockfd;
    struct sockaddr_in broadcast_addr;
    const char* message = static_cast<const char*>(arg);
    //char* message = (char*)arg;
    ssize_t bytes_sent;

    // 创建UDP套接字  
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("socket creation failed");
        pthread_exit(NULL);
    }
    // 允许广播  
    int broadcast_enable = 1;
    if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcast_enable, sizeof(broadcast_enable)) < 0) {
        perror("setsockopt(SO_BROADCAST) failed");
        close(sockfd);
        pthread_exit(NULL);
    }

    // 设置广播地址  
    memset(&broadcast_addr, 0, sizeof(broadcast_addr));
    broadcast_addr.sin_family = AF_INET;
    broadcast_addr.sin_addr.s_addr = inet_addr("255.255.255.255"); // 局域网广播地址  
    broadcast_addr.sin_port = htons(BROADCAST_PORT);

    // 发送广播消息  
    bytes_sent = sendto(sockfd, message, strlen(message), 0, (struct sockaddr*)&broadcast_addr, sizeof(broadcast_addr));
    if (bytes_sent < 0) {
        perror("sendto failed");
    }
    else {
        printf("Broadcast message sent: %s\n", message);
    }

    // 关闭套接字  
    close(sockfd);

    pthread_exit(NULL);
}
void* send_broadcast14(void* arg) {
    int sockfd;
    struct sockaddr_in broadcast_addr;
    char* message = (char*)arg;
    ssize_t bytes_sent;

    // 创建UDP套接字  
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("socket creation failed");
        pthread_exit(NULL);
    }
    // 允许广播  
    int broadcast_enable = 1;
    if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcast_enable, sizeof(broadcast_enable)) < 0) {
        perror("setsockopt(SO_BROADCAST) failed");
        close(sockfd);
        pthread_exit(NULL);
    }

    // 设置广播地址  
    memset(&broadcast_addr, 0, sizeof(broadcast_addr));
    broadcast_addr.sin_family = AF_INET;
    broadcast_addr.sin_addr.s_addr = inet_addr("255.255.255.255"); // 局域网广播地址  
    broadcast_addr.sin_port = htons(BROADCAST_PORT2);

    // 发送广播消息  
    bytes_sent = sendto(sockfd, message, strlen(message), 0, (struct sockaddr*)&broadcast_addr, sizeof(broadcast_addr));
    if (bytes_sent < 0) {
        perror("sendto failed");
    }
    else {
        printf("Broadcast message sent: %s\n", message);
    }

    // 关闭套接字  
    close(sockfd);

    pthread_exit(NULL);
}

void* send_broadcast15(void* arg) {
    int sockfd;
    struct sockaddr_in broadcast_addr;
    char* message = (char*)arg;
    ssize_t bytes_sent;
    const char* message1 = "1";
    const char* message2 = "2";
    // 创建UDP套接字  
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("socket creation failed");
        pthread_exit(NULL);
    }
    // 允许广播  
    int broadcast_enable = 1;
    if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcast_enable, sizeof(broadcast_enable)) < 0) {
        perror("setsockopt(SO_BROADCAST) failed");
        close(sockfd);
        pthread_exit(NULL);
    }

    // 设置广播地址  
    memset(&broadcast_addr, 0, sizeof(broadcast_addr));
    broadcast_addr.sin_family = AF_INET;
    broadcast_addr.sin_addr.s_addr = inet_addr("255.255.255.255"); // 局域网广播地址  
    broadcast_addr.sin_port = htons(BROADCAST_PORT2);

    sleep(6);
    // 发送广播消息  
    bytes_sent = sendto(sockfd, message2, strlen(message2), 0, (struct sockaddr*)&broadcast_addr, sizeof(broadcast_addr));

    sleep(6);
    // 发送广播消息  
    bytes_sent = sendto(sockfd, message1, strlen(message1), 0, (struct sockaddr*)&broadcast_addr, sizeof(broadcast_addr));

    // 关闭套接字  
    close(sockfd);

    pthread_exit(NULL);
}
void* send_broadcast16(void* arg) {
    int sockfd;
    struct sockaddr_in broadcast_addr;
    char* message = (char*)arg;
    ssize_t bytes_sent;

    // 创建UDP套接字  
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("socket creation failed");
        pthread_exit(NULL);
    }
    // 允许广播  
    int broadcast_enable = 1;
    if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcast_enable, sizeof(broadcast_enable)) < 0) {
        perror("setsockopt(SO_BROADCAST) failed");
        close(sockfd);
        pthread_exit(NULL);
    }

    // 设置广播地址  
    memset(&broadcast_addr, 0, sizeof(broadcast_addr));
    broadcast_addr.sin_family = AF_INET;
    broadcast_addr.sin_addr.s_addr = inet_addr("255.255.255.255"); // 局域网广播地址  
    broadcast_addr.sin_port = htons(BROADCAST_PORT3);//就在这改!!!!!!!!!!!!

    // 发送广播消息  
    bytes_sent = sendto(sockfd, message, strlen(message), 0, (struct sockaddr*)&broadcast_addr, sizeof(broadcast_addr));
    if (bytes_sent < 0) {
        perror("sendto failed");
    }
    else {
        printf("Broadcast message sent: %s\n", message);
    }

    // 关闭套接字  
    close(sockfd);

    pthread_exit(NULL);
}
#endif

#if PLATFORM_ANDROID
void UButton_Sheng::Sheng(FString Message)
{
    // 为 Message 分配足够的空间,包括 null 终止符
    int32 Length = Message.Len() + 1;
    char* MessageCStr = new char[Length];
    FMemory::Memcpy(MessageCStr, TCHAR_TO_UTF8(*Message), Length);

    pthread_t thread1, thread2, thread3;
    // 创建线程来发送第一个广播消息  
    if (pthread_create(&thread1, NULL, send_broadcast13, (void*)MessageCStr) != 0) {//调用8888的函数,传入1
        perror("pthread_create for first message failed");
        exit(EXIT_FAILURE);
    }
    // 注意:为每个 pthread_create 调用复制新的字符串或使用其他同步机制来共享同一个字符串
    // 这里为了简化,我们为每个线程都复制了一个新字符串(这不是最高效的方法,但避免了线程安全问题)
    char* MessageCStr2 = new char[Length];
    FMemory::Memcpy(MessageCStr2, TCHAR_TO_UTF8(*Message), Length);

    // 创建线程来发送第二个广播消息  
    if (pthread_create(&thread2, NULL, send_broadcast14, (void*)MessageCStr2) != 0) {//调用8889的第一个函数,传入1
        perror("pthread_create for second message failed");
        // 注意:这里应该加入代码来取消或等待第一个线程,以避免资源泄露  
        // 但为了简单起见,我们直接退出程序(在实际应用中,这是不推荐的)  
        exit(EXIT_FAILURE);
    }
    char* MessageCStr3 = new char[Length];
    FMemory::Memcpy(MessageCStr3, TCHAR_TO_UTF8(*Message), Length);

    // 创建线程来发送第二个广播消息  
    if (pthread_create(&thread3, NULL, send_broadcast16, (void*)MessageCStr3) != 0) {//调用8889的第一个函数,传入1
        perror("pthread_create for second message failed");
        // 注意:这里应该加入代码来取消或等待第一个线程,以避免资源泄露  
        // 但为了简单起见,我们直接退出程序(在实际应用中,这是不推荐的)  
        exit(EXIT_FAILURE);
    }
    // 等待两个线程完成  
    if (pthread_join(thread1, NULL) != 0) {
        perror("pthread_join for first message failed");
    }
    if (pthread_join(thread2, NULL) != 0) {
        perror("pthread_join for second message failed");
    }
    if (pthread_join(thread3, NULL) != 0) {
        perror("pthread_join for first message failed");
    }
    // 释放内存
    delete[] MessageCStr;
    delete[] MessageCStr2;
    delete[] MessageCStr3;
}
#endif

#if PLATFORM_WINDOWS
void UButton_Sheng::Sheng(FString Message)
{
    UE_LOG(LogTemp, Error, TEXT(" %s"), *Message);
}
#endif

void UButton_Sheng::NativeConstruct()
{
}

void UButton_Sheng::CreateDynamicWidget(int32 WidgetID)
{
    // 根据 WidgetID 拼接资源路径
    FString WidgetPath = FString::Printf(TEXT("/Game/widget/Widget_%d.Widget_%d_C"), WidgetID, WidgetID);

    // 加载 Widget Class
    TSubclassOf<UUserWidget> WidgetClass = LoadClass<UUserWidget>(nullptr, *WidgetPath);
    if (WidgetClass)
    {
        // 创建 Widget 实例
        UUserWidget* DynamicWidget = CreateWidget<UUserWidget>(GetWorld(), WidgetClass);
        if (DynamicWidget)
        {
            DynamicWidget->AddToViewport();
            UE_LOG(LogTemp, Log, TEXT("Widget %d created and added to container!"), WidgetID);
        }
    }
    else
    {
        UE_LOG(LogTemp, Error, TEXT("Failed to load Widget Class for ID: %d"), WidgetID);
    }
}

void UButton_Sheng::CreateDynamicWidgetByName(const FString& WidgetName)
{
    // 根据 WidgetName 拼接资源路径
    FString WidgetPath = FString::Printf(TEXT("/Game/UI/%s.%s_C"), *WidgetName, *WidgetName);

    // 加载 Widget Class
    TSubclassOf<UUserWidget> WidgetClass = LoadClass<UUserWidget>(nullptr, *WidgetPath);
    if (WidgetClass)
    {
        // 创建 Widget 实例
        UUserWidget* DynamicWidget = CreateWidget<UUserWidget>(GetWorld(), WidgetClass);
        if (DynamicWidget )
        {
          
        }
    }
    else
    {
        UE_LOG(LogTemp, Error, TEXT("Failed to load Widget Class for Name: %s"), *WidgetName);
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到