UE4 socket UDP通信

  [复制链接]
查看25370 | 回复53 | 2017-3-1 09:52:29 | 显示全部楼层 |阅读模式
最近公司项目要用广播通信 写了一个socket udp通信 最后项目还是用unity 没用上 所以拿出来和大家分享下
server.jpg

这个是接收端的
client.jpg
这个是客户端的 图上这个是发给指定ip的  要给局域网广播的话 将ip 改为255.255.255.255就好了


最后上源码
首先在Build. CS 里添加
PublicDependencyModuleNames.AddRange(new string[] {
    "Core", "CoreUObject", "Engine", "InputCore",

     "Sockets", "Networking"   });


下面是 客户端  服务端的.h .cpp
[mw_shl_code=cpp,true]// Fill out your copyright notice in the Description page of Project Settings.

#pragma once
#include "Networking.h"
#include "GameFramework/Actor.h"
#include "RamaUDPSender.generated.h"

UCLASS()
class ARamaUDPSender : public AActor
{
        GENERATED_UCLASS_BODY()

                bool IsUDP;

        UFUNCTION(BlueprintCallable, Category="UDP")
        bool RamaUDPSender_SendString(FString ToSend);
public:
        TSharedPtr<FInternetAddr>        RemoteAddr;
        FSocket* SenderSocket;
        UFUNCTION(BlueprintCallable, Category = "UDP")
        bool StartUDPSender(const FString& YourChosenSocketName,const FString& TheIP,const int32 ThePort,bool UDP);

public:
        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "UDP")
                bool ShowOnScreenDebugMessages;


        //ScreenMsg
        FORCEINLINE void ScreenMsg(const FString& Msg)
        {
                if (!ShowOnScreenDebugMessages) return;
                GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, *Msg);
        }
        FORCEINLINE void ScreenMsg(const FString& Msg, const float Value)
        {
                if (!ShowOnScreenDebugMessages) return;
                GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString:rintf(TEXT("%s %f"), *Msg, Value));
        }
        FORCEINLINE void ScreenMsg(const FString& Msg, const FString& Msg2)
        {
                if (!ShowOnScreenDebugMessages) return;
                GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString:rintf(TEXT("%s %s"), *Msg, *Msg2));
        }


public:

        /** Called whenever this actor is being removed from a level */
        virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
};[/mw_shl_code]

[mw_shl_code=cpp,true]// Fill out your copyright notice in the Description page of Project Settings.

#include "UDPSendReceive.h"
#include "RamaUDPSender.h"


ARamaUDPSender::ARamaUDPSender(const FObjectInitializer& ObjectInitializer)
        : Super(ObjectInitializer)
{
        SenderSocket = NULL;

        ShowOnScreenDebugMessages = true;
}

void ARamaUDPSender::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
        Super::EndPlay(EndPlayReason);
        //~~~~~~~~~~~~~~~~

        if (SenderSocket) //Clear all sockets!
        {
                SenderSocket->Close();
                ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(SenderSocket);
        }
}



bool ARamaUDPSender::RamaUDPSender_SendString(FString ToSend)                 //发送消息处理
{
        if (!SenderSocket)
        {
                ScreenMsg("No sender socket");
                return false;
        }
        //~~~~~~~~~~~~~~~~
        //发送消息
        int32 BytesSent = 0;
        FString serialized =ToSend;
        TCHAR *serializedChar = serialized.GetCharArray().GetData();
        int32 size = FCString::Strlen(serializedChar);
        int32 sent = 0;
        //SenderSocket->SendTo(Writer.GetData(), Writer.Num(), BytesSent, *RemoteAddr);
        SenderSocket->SendTo((uint8*)TCHAR_TO_UTF8(serializedChar), size, BytesSent, *RemoteAddr);//发送给远端地址

        if (BytesSent <= 0)
        {
                const FString Str = "Socket is valid but the receiver received 0 bytes, make sure it is listening properly!";
                UE_LOG(LogTemp, Error, TEXT("%s"), *Str);
                ScreenMsg(Str);
                return false;
        }

        ScreenMsg("UDP Send Succcess! INFO Sent = ", ToSend);

        return true;
}


bool ARamaUDPSender::StartUDPSender(const FString & YourChosenSocketName, const FString & TheIP, const int32 ThePort, bool UDP)///////////初始化远端IP 发送信息前
{
        //FIPv4Endpoint Endpoint(FIPv4Address::Any, 6789);
        //Create Remote Address.
        RemoteAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();

        bool bIsValid;
        RemoteAddr->SetIp(*TheIP, bIsValid);
        RemoteAddr->SetPort(ThePort);

        if (!bIsValid)
        {
                ScreenMsg("Rama UDP Sender>> IP address was not valid!", TheIP);
                return false;
        }
       

        SenderSocket = FUdpSocketBuilder(*YourChosenSocketName)
                .AsReusable()
                .WithBroadcast()/////////////广播
                .WithSendBufferSize(2 * 1024 * 1024)
                //.BoundToEndpoint(Endpoint)
                ;


        //check(SenderSocket->GetSocketType() == SOCKTYPE_Datagram);

        //Set Send Buffer Size
        int32 SendSize = 2 * 1024 * 1024;
        SenderSocket->SetSendBufferSize(SendSize, SendSize);
        SenderSocket->SetReceiveBufferSize(SendSize, SendSize);
        if (bIsValid)
        {
                bIsValid = true;
        }
        return bIsValid;
       
}
[/mw_shl_code]


[mw_shl_code=cpp,true]// Fill out your copyright notice in the Description page of Project Settings.

#pragma once
#include "Networking.h"
#include "GameFramework/Actor.h"
#include "RamaUDPReceiver.generated.h"


UCLASS()
class ARamaUDPReceiver : public AActor
{
        GENERATED_UCLASS_BODY()
public:
       
        virtual void Tick(float DeltaSeconds) override;


        //====================================================

public:
        FSocket* ListenSocket;
       

        FUdpSocketReceiver* UDPReceiver = nullptr;


        UFUNCTION(BlueprintCallable, Category="UDP")
        void StartUDPReceiver(const FString& YourChosenSocketName,const FString& TheIP,const int32 ThePort, bool& success);
        UFUNCTION(BlueprintPure, Category = "UDP")
                void DataRecv(FString& str,bool& success);

        //ScreenMsg
        FORCEINLINE void ScreenMsg(const FString& Msg)
        {
                GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, *Msg);
        }
        FORCEINLINE void ScreenMsg(const FString& Msg, const float Value)
        {
                GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString:rintf(TEXT("%s %f"), *Msg, Value));
        }
        FORCEINLINE void ScreenMsg(const FString& Msg, const FString& Msg2)
        {
                GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString:rintf(TEXT("%s %s"), *Msg, *Msg2));
        }


public:

        /** Called whenever this actor is being removed from a level */
        virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
};
[/mw_shl_code]


[mw_shl_code=cpp,true]// Fill out your copyright notice in the Description page of Project Settings.

#include "UDPSendReceive.h"
#include "RamaUDPReceiver.h"


ARamaUDPReceiver::ARamaUDPReceiver(const FObjectInitializer& ObjectInitializer)
        : Super(ObjectInitializer)
{
        ListenSocket = NULL;
}

void ARamaUDPReceiver::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
        Super::EndPlay(EndPlayReason);
        //~~~~~~~~~~~~~~~~

        delete UDPReceiver;
        UDPReceiver = nullptr;

        //Clear all sockets!
        //                makes sure repeat plays in Editor dont hold on to old sockets!
        if (ListenSocket)
        {
                ListenSocket->Close();
                ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(ListenSocket);
        }
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//Start UDP Receiver
void ARamaUDPReceiver::StartUDPReceiver(const FString& YourChosenSocketName,const FString& TheIP,const int32 ThePort, bool& success) // 接收器初始化  接收信息前
{

        TSharedRef<FInternetAddr> targetAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
        FIPv4Address Addr;
        FIPv4Address:arse(TheIP, Addr);

        //Create Socket
        FIPv4Endpoint Endpoint(FIPv4Address::Any, ThePort);  //所有ip地址本地
        //FIPv4Endpoint Endpoint(Addr, ThePort);                 //指定ip地址
        ListenSocket = FUdpSocketBuilder(*YourChosenSocketName)
                .AsNonBlocking()
                .AsReusable()
                .BoundToEndpoint(Endpoint)
                .WithReceiveBufferSize(2 * 1024 * 1024)
               
        ;
        //BUFFER SIZE
        int32 BufferSize = 2 * 1024 * 1024;
        ListenSocket->SetSendBufferSize(BufferSize, BufferSize);
        ListenSocket->SetReceiveBufferSize(BufferSize, BufferSize);

        if (!ListenSocket)
        {
                ScreenMsg("No socket");
                success = false;

        }
        if (ListenSocket)
        {
                ScreenMsg("The receiver is initialized");
                success = true;
        }

        //return true;
}

void ARamaUDPReceiver:ataRecv(FString& str, bool& success)              //接收消息处理
{
       
        if (!ListenSocket)
        {
                ScreenMsg("No sender socket");
                success = false;
                //return success;
        }
        TSharedRef<FInternetAddr> targetAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
        TArray<uint8> ReceivedData;//定义一个接收器
        uint32 Size;
        if (ListenSocket->HasPendingData(Size))
        {
                success = true;
                str = "";
                uint8 *Recv = new uint8[Size];
                int32 BytesRead = 0;

                ReceivedData.SetNumUninitialized(FMath::Min(Size, 65507u));
                ListenSocket->RecvFrom(ReceivedData.GetData(), ReceivedData.Num(), BytesRead, *targetAddr);//创建远程接收地址
                char ansiiData[1024];
                memcpy(ansiiData, ReceivedData.GetData(), BytesRead);//拷贝数据到接收器
                ansiiData[BytesRead] = 0;                            //判断数据结束
                FString debugData = ANSI_TO_TCHAR(ansiiData);         //字符串转换
                str = debugData;
           // memset(ansiiData,0,1024);//清空       

        }
        else
        {
                success = false;
        }
        //return success;
}


void ARamaUDPReceiver::Tick(float DeltaSeconds)
{
        Super::Tick(DeltaSeconds);
}

[/mw_shl_code]
瘦Tiger | 2017-3-1 09:59:23 | 显示全部楼层
感谢分享!
回复

使用道具 举报

powerwb | 2017-3-1 10:10:19 | 显示全部楼层
干货好东西 谢谢分享
回复 支持 反对

使用道具 举报

bluemain | 2017-3-1 10:10:50 | 显示全部楼层
感谢大神分享!~~
回复 支持 反对

使用道具 举报

zhaishengfu | 2017-3-1 10:20:19 | 显示全部楼层
干活猴赛
回复

使用道具 举报

__________ | 2017-3-1 12:10:37 | 显示全部楼层
感谢分享
回复

使用道具 举报

2659365465 | 2017-3-1 12:39:52 | 显示全部楼层
666这个必须赞。楼主,可以给个qq联系方式吗?以后想向您请教~
回复 支持 反对

使用道具 举报

2659365465 | 2017-3-1 13:13:55 | 显示全部楼层
楼主,这个报了好多错误呀,
回复 支持 反对

使用道具 举报

webcq | 2017-3-1 16:24:30 | 显示全部楼层
感谢分享!!!
回复

使用道具 举报

承无影剑 | 2017-3-1 17:55:27 | 显示全部楼层
很好的学习资料,谢谢大神分享
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

16

主题

335

回帖

4170

积分

高阶编码师

积分
4170