UE4 使用Socket

在配置文件加上Networking。

使用socket加以上头文件

并加上ISocketSubsystem的头文件

 通过传过来的IP与端口号进行一个绑定,第一行就是将BindIP分割然后分别放进ip的四个值内(A,B,C,D),然后创建一个FInternetAddr类型的智能指针,将ip的值与外界传来的端口号对FInternetAddr进行一个初始化赋值,最后对让socket对地址进行一个绑定。

服务器进行一个监听,看客户端是否发出消息让服务器进行接收

 

 对消息进行接收

客户端发送消息,先将要发送的字符串进行char的转化。

然后对处理后的数据发送到指定地址

FSocket::HasPendingData将返回一个值,通知您是否
从套接字读取是安全的。

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

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Networking/Public/Interfaces/IPv4/IPv4Address.h"
#include "ServerSocket.generated.h"

UCLASS()
class MYCTEST_API AServerSocket : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	AServerSocket();

	FSocket* ServerSocket;
	FSocket* ClientSocket;

	FTimerHandle SocketTimerHandle;

	FIPv4Address ip;

	FVector currentLoc;

	float SocketDelta;

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	virtual void EndPlay(const EEndPlayReason::Type EEndPlayReason);

	bool CreateSocket();

	//Bind创建的Socket 需要ip和port
	bool BindSocket(const FString& BindIP, const int32 BindPort);

	//监听Socket
	bool ListenSocket(int32 MaxConnectionNum);

	//Accept Client
	bool AcceptSocket();

	//收发消息
	bool sendMsg(const FString& Msg);

	FString RecvMsg();

	//转换函数
	FString StringFromBinaryArray(const TArray<uint8>& BinaryArray) {
		return FString(ANSI_TO_TCHAR(reinterpret_cast<const char*>(BinaryArray.GetData())));
	}

	UFUNCTION(BlueprintCallable)
	void Test(const FString &BindIP, const int32 Port, const int32 MaxListener);

	void HandleFunc();
};
// Fill out your copyright notice in the Description page of Project Settings.


#include "ServerSocket.h"
#include "SocketSubsystem.h"
#include "Sockets.h"
#include "Engine/World.h"
#include "TimerManager.h"
#include "Kismet/KismetStringLibrary.h"
#include "UObject/ConstructorHelpers.h"
#include "Components/StaticMeshComponent.h"
#include "Engine/StaticMesh.h"

// Sets default values
// Called when the game starts or when spawned

#define SPHERE_PATH TEXT("/Game/StarterContent/Shapes/Shape_Sphere")

AServerSocket::AServerSocket()
{
	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	currentLoc = FVector(0.f, 0.f, 0.f);
	UStaticMeshComponent* staticMeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
	struct FContructor {
		ConstructorHelpers::FObjectFinderOptional<UStaticMesh> Mesh;
		FContructor() : Mesh(SPHERE_PATH) {}
	};

	static FContructor ConstructorStatics;

	auto tempMesh = ConstructorStatics.Mesh;

	staticMeshComponent->SetupAttachment(RootComponent);

	if (tempMesh.Succeeded()) {
		staticMeshComponent->SetStaticMesh(tempMesh.Get());
	}

}

// Called when the game starts or when spawned
void AServerSocket::BeginPlay()
{
	Super::BeginPlay();

#if 0
	APlayerController* myPlayerController = UGameplayStatics::GetPlayerController(this, 0);

	if (myPlayerController) {
		this->EnableInput(myPlayerController);
	}
#endif

}

// Called every frame
void AServerSocket::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	SocketDelta = DeltaTime;
	AddActorWorldOffset(currentLoc);
	GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, FString::Printf(TEXT("%d-%d-%d"), currentLoc.X, currentLoc.Y, currentLoc.Z));
}

void AServerSocket::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
	Super::EndPlay(EndPlayReason);
	if (ServerSocket) {
		ServerSocket->Close();
		ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(ServerSocket);
	}
	if (ClientSocket) {
		ClientSocket->Close();
		ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(ClientSocket);
	}

}

bool AServerSocket::CreateSocket()
{
	ServerSocket = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateSocket(NAME_Stream, "Send Information", false);
	if (!ServerSocket) {
		return false;
	}

	return true;
}

bool AServerSocket::BindSocket(const FString& BindIP, const int32 BindPort)
{
	FIPv4Address::Parse(BindIP, ip);
	TSharedPtr<FInternetAddr> addr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
	addr->SetIp(ip.Value);
	addr->SetPort(BindPort);
	bool bBind = ServerSocket->Bind(*addr);

	return bBind;
}

bool AServerSocket::ListenSocket(int32 MaxConnectionNum)
{
	ServerSocket->Listen(MaxConnectionNum);

	return false;
}

bool AServerSocket::AcceptSocket()
{
	ClientSocket = ServerSocket->Accept("Send Information");

	if (!ClientSocket)	return false;

	return true;
}

bool AServerSocket::sendMsg(const FString& Msg)
{
	TSharedPtr<FInternetAddr> addr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
	FText outputSample = FText::FromString(addr->ToString(false));
	GEngine->AddOnScreenDebugMessage(-1, 100.f, FColor::Yellow, addr->ToString(true));
	FString tempMsg = Msg;
	TCHAR* MsgChar = tempMsg.GetCharArray().GetData();
	int32 size = FCString::Strlen(MsgChar) + 1;
	int sent = 0;
	bool bSend;
	if (ClientSocket) {
		bSend = ClientSocket->SendTo((uint8*)TCHAR_TO_UTF8(MsgChar), size, sent, *addr);
	}
	bSend ? GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, TEXT("Socket Sent Success")) : GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("Socket Failed"));

	return bSend;
}

FString AServerSocket::RecvMsg()
{
	TSharedPtr<FInternetAddr> addr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
	TArray<uint8> ReceiveData;
	FString ReceivedUE4String = "";
	uint32 Size;

	if (ClientSocket->HasPendingData(Size)) {
		uint8* Recv = new uint8[Size];
		ReceiveData.SetNumUninitialized(FMath::Min(Size, 65507u));
		int32 ByteRead = 0;
		ClientSocket->RecvFrom(ReceiveData.GetData(), ReceiveData.Num(), ByteRead, *addr);
		if (ReceiveData.Num() > 0) {
			GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, FString::Printf(TEXT("Data Bytes Read-> %d"), ReceiveData.Num()));
			ReceivedUE4String = StringFromBinaryArray(ReceiveData);
			GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, FString::Printf(TEXT("Data String Read-> %d"), ReceiveData.Num()));
		}
		else {
			GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, FString::Printf(TEXT("Data Byte Read Failed"), ReceiveData.Num()));
		}
		return ReceivedUE4String;
	}

	return ReceivedUE4String;
}

void AServerSocket::Test(const FString& BindIP, const int32 Port, const int32 MaxListener) {
	if (CreateSocket()) {
		if (BindSocket(BindIP, Port)) {
			if (ListenSocket(MaxListener)) {
				if (AcceptSocket()) {
					UWorld* world = GetWorld();
					world->GetTimerManager().SetTimer(SocketTimerHandle, this, &AServerSocket::HandleFunc, SocketDelta, true);
				}
			}
		}
	}
}

void AServerSocket::HandleFunc()
{
	bool outIsValid = false;
	UKismetStringLibrary::Conv_StringToVector(RecvMsg(), currentLoc, outIsValid);
}

猜你喜欢

转载自blog.csdn.net/qqQQqsadfj/article/details/127654984#comments_26448268