상세 컨텐츠

본문 제목

언리얼과 클라이언트 기기(pc, ios, android 등등) 네트워크 통신 관련

게임엔진관련/언리얼 엔진

by AlrepondTech 2020. 9. 20. 04:56

본문

반응형
728x170

 

 

 

=================================

=================================

=================================

 

 

 

 

출처: http://cafe.naver.com/unrealenginekr/5737

 

FSocket 서버구현까진 완성했습니다.

 

그런데 이 Class를 새로 만들고 난뒤에 어디에서 객체를 생성해야할지 모르겠습니다.

 

GameMode에서 생성해도 생성자가 없어서 Call을 어디서 해야할지 모르겠고

Pawn에 직접 생성해도 FSocket 클라이언트는 괜찮은데

서버를 생성하면 컴퓨터 자체가 에러가 뜹니다.

 

어디에 FSocket를 붙여야 할까요 ㅠㅠ

 

 

  • 저도 공부한지 얼마안되서 모르겠는데
    소켓쓰는 네트워크클래스를 액터로 만들었어요
    액터클래스를 에디터에서 끌어놔도되고 pawn 에서 생성해줘도되구용

  •   라테르
    2015.08.26. 15:48답글지금 pawn으로 새로 만들어서 winsock2를 이용해서 하고있는데
    accept()에서 UE4Editor가 응답없음 뜨네요 ㅠㅠ
  • 신고
  •   기메경
    2015.08.26. 15:50답글라테르 이거만 봐서는 뭐가 문젠지 ;; ㅠㅠ
  • 신고
  •   라테르
    2015.08.26. 21:18답글기메경 blocking accept()를 써서 return이 안되서 발생한 문제로 밝혀졌습니다 ㅋㅋ ㅠ
    nonblocing을 써봤지만 똑같은 현상이 나왔구
    이젠 멀티쓰레드를 이용한 방법으로 하고있는데,
    쓰레드 개념이 잘 잡혀있지 않아서 잘 안되네요 ㅋㅋ ㅠ
  • 신고
  •   Kusai
    2016.01.03. 09:02답글라테르 저도 언리얼엔진에 네트워크를 붙이려 winsock2.h 인클루드를 하고있는데 "DWORD" is ambiguous,
    "INT" is ambiguous 오류나면서 안되네요.. 혹시 방법을 아신다면 알려주실 수 있으신가요 ??
  • 신고

 

 

=================================

=================================

=================================

 

 

출처: https://answers.unrealengine.com/questions/256244/ftcpsocketbuilder-asnonblocking-not-working.html

 

FTcpSocketBuilder AsNonBlocking not working

 

 

I succeeded to setup a TCP connection with my server , its working great !

But i felt disappointed about the Connect step. Indeed , when the IP/Port are correct , the connection is established at once . But , when the IP is wrong or the server is shutdown , the editor freeze at least 30 sec then the log (that says i can't connect) shows up.

I finally found the problem : FTcpSocketBuilder("SOCKETNAME").AsNonBlocking().Build() was not setting the socket AsNonBlocking.

I had to add "TCPSocket->SetNonBlocking(true);" in order to make it work so the editor doesn't freeze anymore when the server is shutdown.

Is that a bug or was i doing that wrong ?

Plateform : OSX Yosemite, Editor 4.8.1

 

Product Version: UE 4.8

Tags:unreal engine 4c++bug reportnetwork

screen shot 2015-07-11 at 11.18.09.png (140.8 kB)

more ▼

asked Jul 11 '15 at 6:24 PM

Sumenia 
1  2  3

 Sumenia Jul 11 '15 at 7:10 PM

 

Well , i was so glad my editor didn't freeze anymore when the server is shutdown that i didn't test when the server is alive..... and TCPSocket->SetNonBlocking(true) made it impossible to connect ....

I change the way i create the socket by doing : TCPSocket = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateSocket(NAME_Stream, TEXT("default"), false);

And now its working flawlessly !

I still don't understand why what i did was wrong so i let this post up as that sound buggy for me.

 

 

 

=================================

=================================

=================================

 

 

출처: https://translate.googleusercontent.com/translate_c?depth=1&hl=ko&prev=search&rurl=translate.google.co.kr&sl=en&u=http://pastebin.com/1Qw1sJ7u&usg=ALkJrhitFJ8sufpE5aa5KgFa7RxmrswRAg

 

//PlayerController.cpp
 
#include "FYPProject.h"
#include <string>
#include "NetworkPlayerController.h"
 
void ANetworkPlayerController::Laaaaaauuuunch()
{
    //IP = 127.0.0.1, Port = 8890 for my Python test case
    if (!StartTCPReceiver("RamaSocketListener", "127.0.0.1", 8890))
    {
        //UE_LOG  "TCP Socket Listener Created!"
        return;
    }
 
    //UE_LOG  "TCP Socket Listener Created! Yay!"
}
 
//Rama's Start TCP Receiver
bool ANetworkPlayerController::StartTCPReceiver(
    const FString& YourChosenSocketName,
    const FString& TheIP,
    const int32 ThePort
    ){
    //Rama's CreateTCPConnectionListener
    ListenerSocket = CreateTCPConnectionListener(YourChosenSocketName, TheIP, ThePort);
 
    //Not created?
    if (!ListenerSocket)
    {
        GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("StartTCPReceiver>> Listen socket could not be created! ~> %s %d"), *TheIP, ThePort));
        return false;
    }
 
    //Start the Listener! //thread this eventually
    GetWorldTimerManager().SetTimer(this,
        &ANetworkPlayerController::TCPConnectionListener, 0.01, true);
 
    return true;
}
//Format IP String as Number Parts
bool ANetworkPlayerController::FormatIP4ToNumber(const FString& TheIP, uint8(&Out)[4])
{
    //IP Formatting
    TheIP.Replace(TEXT(" "), TEXT(""));
 
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //                         IP 4 Parts
 
    //String Parts
    TArray<FString> Parts;
    TheIP.ParseIntoArray(&Parts, TEXT("."), true);
    if (Parts.Num() != 4)
        return false;
 
    //String to Number Parts
    for (int32 i = 0; i < 4; ++i)
    {
        Out[i] = FCString::Atoi(*Parts[i]);
    }
 
    return true;
}
//Rama's Create TCP Connection Listener
FSocket* ANetworkPlayerController::CreateTCPConnectionListener(const FString& YourChosenSocketName, const FString& TheIP, const int32ThePort, const int32 ReceiveBufferSize)
{
    uint8 IP4Nums[4];
    if (!FormatIP4ToNumber(TheIP, IP4Nums))
    {
        VShow("Invalid IP! Expecting 4 parts separated by .");
        return false;
    }
 
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
    //Create Socket
    FIPv4Endpoint Endpoint(FIPv4Address(IP4Nums[0], IP4Nums[1], IP4Nums[2], IP4Nums[3]), ThePort);
    FSocket* ListenSocket = FTcpSocketBuilder(*YourChosenSocketName)
        .AsReusable()
        .BoundToEndpoint(Endpoint)
        .Listening(8);
 
    //Set Buffer Size
    int32 NewSize = 0;
    ListenSocket->SetReceiveBufferSize(ReceiveBufferSize, NewSize);
 
    //Done!
    return ListenSocket;
}
//Rama's TCP Connection Listener
void ANetworkPlayerController::TCPConnectionListener()
{
    //~~~~~~~~~~~~~
    if (!ListenerSocket) return;
    //~~~~~~~~~~~~~
 
    //Remote address
    TSharedRef<FInternetAddr> RemoteAddress = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
    bool Pending;
 
    // handle incoming connections
    if (ListenerSocket->HasPendingConnection(Pending) && Pending)
    {
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        //Already have a Connection? destroy previous
        if (ConnectionSocket)
        {
            ConnectionSocket->Close();
            ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(ConnectionSocket);
        }
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
        //New Connection receive!
        ConnectionSocket = ListenerSocket->Accept(*RemoteAddress, TEXT("RamaTCP Received Socket Connection"));
 
        if (ConnectionSocket != NULL)
        {
            //Global cache of current Remote Address
            RemoteAddressForConnection = FIPv4Endpoint(RemoteAddress);
 
            //UE_LOG "Accepted Connection! WOOOHOOOO!!!";
 
            //can thread this too
            GetWorldTimerManager().SetTimer(this,
                &ANetworkPlayerController::TCPSocketListener, 0.01, true);
        }
    }
}
 
//Rama's String From Binary Array
//This function requires
//      #include <string>
FString ANetworkPlayerController::StringFromBinaryArray(const TArray<uint8>& BinaryArray)
{
    //Create a string from a byte array!
    std::string cstr(reinterpret_cast<const char*>(BinaryArray.GetData()), BinaryArray.Num());
    return FString(cstr.c_str());
}
 
//Rama's TCP Socket Listener
void ANetworkPlayerController::TCPSocketListener()
{
    //~~~~~~~~~~~~~
    if (!ConnectionSocket) return;
    //~~~~~~~~~~~~~
 
 
    //Binary Array!
    TArray<uint8> ReceivedData;
 
    uint32 Size;
    while (ConnectionSocket->HasPendingData(Size))
    {
        ReceivedData.Init(FMath::Min(Size, 65507u));
 
        int32 Read = 0;
        ConnectionSocket->Recv(ReceivedData.GetData(), ReceivedData.Num(), Read);
 
        //GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("Data Read! %d"), ReceivedData.Num()));
    }
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
    if (ReceivedData.Num() <= 0)
    {
        //No Data Received
        return;
    }
 
    VShow("Total Data read!", ReceivedData.Num());
    GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("Data Bytes Read ~> %d"), ReceivedData.Num()));
 
 
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //                      Rama's String From Binary Array
    const FString ReceivedUE4String = StringFromBinaryArray(ReceivedData);
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 
    VShow("As String!!!!! ~>", ReceivedUE4String);
    GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("As String Data ~> %s"), *ReceivedUE4String));
}

 

 

=================================

=================================

=================================

 

 

 

 

출처: https://forums.unrealengine.com/showthread.php?54343-Communication-Between-UE4-and-a-Python-UDP-Server

 

 

Communication Between UE4 and a Python UDP Server

All,

I have spent a while searching and learning on how to implement the talking between UE4 and Python. I have used Rama's code as well as some random ones on the internet to get me where I am. Below is the code I am using to talk to a Python UDP server that will handle all my non game related network code (e.g. Logging into the server and checking user info, sending remember tokens, retrieving saved characters and anything else you can think of that doesn't rely on the game engine.) I hope this helps.

Python Code

UDPServer.py

You could do the below differently and even put the handler in a different thread.

Code:

##################################
## UDP Server to Talk to UE4
##################################

### Imports
import socket
import sys
from UDPRequestHandler import *

HOST = ''
PORT = 8800

# Create the UDP Socket
try:
    socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    #socket.setblocking(false)
    print("Socket Created")
except:
    print("Failed to create socket.")
    sys.exit()

# Bind socket to local host and port
try:
    socket.bind((HOST, PORT))
except:
    print("Bind failed.")
    sys.exit()
    
print("Socket bind complete.")

# Now keep talking to clients

while 1:

    # Receive data from client (data, addr)
    d = socket.recvfrom(1024)
    data = str(d[0], "utf-8")
    addr = d[1]

    # Print to the server who made a connection.
    print("{} wrote:".format(addr))
    print(data)
        
    # Now have our UDP handler handle the data
    myUDPHandler = UDPRequestHandler()
    myResponse = myUDPHandler.handle(data)

    # Respond back
    print(myResponse)
    socket.sendto(bytes(myResponse, 'utf-8'), addr)
    
socket.close()


UDPRequestHandler.py

This is called to handle each connection.

Code:

########################
## UDPHandler Class
########################

### Imports
import socketserver
import json
from passlib.hash import pbkdf2_sha256
from UDPPostgreSQLConnector import *

class UDPRequestHandler:

    def checkLogin(self, email, password):

        # This checks to see if the player is who they say they are.
        # If so send back a dict with the players ID and remember_token.

        myDB = UDPPostgreSQLConnector()

        pswdToCheck = pbkdf2_sha256.encrypt(password, rounds=200000,
                                            salt_size=16)
 
        dbResponse = myDB.selectWhere("game.players",
                        "*", "email = '" + email + "'")
        return dbResponse
 
        #if (pbkdf2_sha256.verify(password, dbResponse['password'])):

        #   return "Logged In"
        #else:
        #   return "Invalid Password"

    def handle(self, data):
        myData = json.loads(data)
              

        if myData['Request'] == 'Login':

            ResponseStr = "{'Return': " + self.checkLogin(myData['Email'],
                                                          myData['Password'])
        elif myData['Request'] == 'Test':

            ResponseStr = pbkdf2_sha256.encrypt(myData['Password'], rounds=5000,
                                            salt_size=16)
        else:
            ResponseStr = "I hear you"
                                     
        response = ResponseStr
        
        return response

UDPPostgreSQLConnector.py

This handles all database work. This is basic and will be expanded as needed. But you should get the idea. Also, sensitive info stripped.

Code:

#######################
## PostgreSQL Class
#######################

import psycopg2 as mdb
import psycopg2.extras
import sys


class UDPPostgreSQLConnector:

    connection = None         

    def openConnection(self, db):

        conString = "host='999.888.77.6' dbname='game' user='secret' password='secret'"

        # opens a connection to the db
        self.connection = mdb.connect(conString)

    def closeConnection(self):

        #Closes the connection
        self.connection.close()

    def selectWhere(self, table, columns, where):

        # Use like
        #selectWhere("users", "id", "email='lll'")

        try:

            self.openConnection(self.db)

            cur = self.connection.cursor(cursor_factory=mdb.extras.RealDictCursor)

            cur.execute("SELECT " + columns + " FROM " + table +
                        " WHERE " + where) 

            data = cur.fetchone()

            if (data == ""):
                data = "No users."

            cur.close()

        except mdb.DatabaseError as e:

            data = 'Error %s' % e
            #sys.exit(1)

        finally:

            if self.connection:
                 self.closeConnection()

        return data

 

The python code is all stored on my Ubuntu server and not on my development computer. Below is the different classes and code for my test game. 

UE4 C++ Code

UDP Networking Wrapper (H)

This is the main object I use in blueprints to send and receive.

Code:

#include "Object.h"
#include "Networking.h"
#include "Json.h"
#include "UDPReceiveWorker.h"
#include "UDPNetworkingWrapper.generated.h"

/**
 * 
 */
UCLASS(BlueprintType, Blueprintable)
class GAME_API UUDPNetworkingWrapper : public UObject
{
	GENERATED_BODY()

public:
	//----------------------------------------------------------
	// Construction

	/**
	* Creates and initializes a new UDPNetworking object.
	*
	* @param Description - The description of the socket for debug purposes.
	* @param SenderSocketName - Name of the sender socket for debug purposes.
	* @param TheIP - IP of the the machine you want to send a message too.
	* @param ThePort - The port of the machine you are trying to talk to.
	* @param BufferSize - The size of the buffer for the socket
	* @param AllowBroadCast - Allow broadcasting on this socket?
	* @param Bound - Bind socket to the ip and port?
	* @param Reusable - Is this socket reusable?
	* @param Blocking - Is this socket blocking other data?
	*/
	UFUNCTION(BlueprintPure, Category = "UDPNetworking")
		static UUDPNetworkingWrapper* ConstructUDPWrapper(const FString& Description, const FString& SenderSocketName, const FString& TheIP, const int32 ThePort, const int32 BufferSize,
			const bool AllowBroadcast, const bool Bound, const bool Reusable, const bool Blocking);

	static UUDPNetworkingWrapper* Constructor();

	/**
	* Sends the supplied message
	* @param Message The message to be sent.
	*/
	UFUNCTION(BlueprintCallable, Category = "UDPNetworking")
		bool sendMessage(FString Message);

	//--------------------------------------------------------
	// Destruction and reset

	/** Destroys all data */
	UFUNCTION(BlueprintCallable, Category = "UDPNetworking")
		void UDPDestructor();

	//// Grab Data
	UFUNCTION(BlueprintCallable, Category = "UDPNetworking")
		bool anyMessages();


	/** Test Look for message */
	UFUNCTION(BlueprintCallable, Category = "UDPNetworking")
		FString GrabWaitingMessage();

	static FString StringFromBinaryArray(const TArray<uint8>&  BinaryArray);
	
private:

	// Holds the socket we are sending on
	FSocket* SenderSocket;

	// Description for debugging
	FString SocketDescription;

	// Remote Address
	FIPv4Endpoint RemoteEndPoint;
	FIPv4Address RemoteAdress;

	// Socket Subsystem
	ISocketSubsystem* SocketSubsystem;

	//UDPReceiveWorker* myRecieverWorker;
	// The data
	TArray<uint8> ReceivedData;

 

UDP Networking Wrapper (C)

CPP

Code:

#include "Game.h"
#include "UDPNetworkingWrapper.h"

UUDPNetworkingWrapper* UUDPNetworkingWrapper::Constructor()
{
	return (UUDPNetworkingWrapper*)StaticConstructObject(UUDPNetworkingWrapper::StaticClass());
}

UUDPNetworkingWrapper* UUDPNetworkingWrapper::ConstructUDPWrapper(const FString& Description, 
const FString& SenderSocketName, const FString& TheIP, const int32 ThePort, const int32 BufferSize,
	const bool AllowBroadcast, const bool Bound, const bool Reusable, const bool Blocking)
{

	UUDPNetworkingWrapper* wrapper = Constructor();

	wrapper->SocketSubsystem = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM);
	FIPv4Address::Parse(TheIP, wrapper->RemoteAdress);

	wrapper->RemoteEndPoint = FIPv4Endpoint(wrapper->RemoteAdress, ThePort);

	// First set our socket null
	wrapper->SenderSocket = nullptr;

	if (wrapper->SocketSubsystem != nullptr) // If socket subsytem is good
	{
		wrapper->SenderSocket = wrapper->SocketSubsystem->CreateSocket(NAME_DGram, 
        *Description, true);

		if (wrapper->SenderSocket != nullptr) // Is our socket created
		{
			// Setup the socket 
			bool Error = !wrapper->SenderSocket->SetNonBlocking(!Blocking) ||
				!wrapper->SenderSocket->SetReuseAddr(Reusable) ||
				!wrapper->SenderSocket->SetBroadcast(AllowBroadcast) ||
				!wrapper->SenderSocket->SetRecvErr();

			if (!Error)
			{
				if (Bound)
				{
					Error = !wrapper->SenderSocket->Bind(*wrapper->RemoteEndPoint.ToInternetAddr());
				}
			}

			if (!Error)
			{
				int32 OutNewSize;

				wrapper->SenderSocket->SetReceiveBufferSize(BufferSize, OutNewSize);
				wrapper->SenderSocket->SetSendBufferSize(BufferSize, OutNewSize);
			}

			if (Error)
			{
				GLog->Logf(TEXT("FUdpSocketBuilder: Failed to create the socket %s as configured"), *Description);

				wrapper->SocketSubsystem->DestroySocket(wrapper->SenderSocket);
				wrapper->SenderSocket = nullptr;
			}
		}

	}


	return wrapper;
}

bool UUDPNetworkingWrapper::sendMessage(FString Message)
{
	if (!SenderSocket) return false;

	int32 BytesSent;
	FTimespan waitTime = FTimespan(10);
	TCHAR *serializedChar = Message.GetCharArray().GetData();
	int32 size = FCString::Strlen(serializedChar);
	int32 sent = 0;

	// Send to
	//myRecieverWorker = UDPReceiveWorker::JoyInit(SenderSocket, waitTime);
	bool success = SenderSocket->SendTo((uint8*)TCHAR_TO_UTF8(serializedChar), size,
    BytesSent, *RemoteEndPoint.ToInternetAddr());
	
    if (success && BytesSent > 0) // Success
	{
		return true;
	}
	else
	{
		return false;
	}
}

FString UUDPNetworkingWrapper::GrabWaitingMessage()
{
	uint32 Size;

	TSharedRef<FInternetAddr> Sender = SocketSubsystem->CreateInternetAddr();
	
	while (SenderSocket->HasPendingData(Size))
	{
		int32 Read = 0;
		ReceivedData.Init(FMath::Min(Size, 65507u));
		SenderSocket->RecvFrom(ReceivedData.GetData(), ReceivedData.Num(), Read, *Sender);
	}
	

	return StringFromBinaryArray(ReceivedData);

}

bool UUDPNetworkingWrapper::anyMessages()
{

	uint32 Size;

	if (SenderSocket->HasPendingData(Size))
	{
		return true;
	}
	
	return false;
}

FString UUDPNetworkingWrapper::StringFromBinaryArray(const TArray<uint8>& BinaryArray)
{
	//Create a string from a byte array!
	const std::string cstr(reinterpret_cast<const char*>(BinaryArray.GetData()), BinaryArray.Num());

	//FString can take in the c_str() of a std::string
	return FString(cstr.c_str());

}

void UUDPNetworkingWrapper::UDPDestructor()
{
	SocketSubsystem->DestroySocket(SenderSocket);
	SenderSocket = nullptr;
	SocketSubsystem = nullptr;
	//myRecieverWorker = nullptr;
}

 

 

Then in the editor just create an object with the UDPNetworkingWrapper class. Make a call to the constructor passing all the info. Then with the object you can send out messages and make a check for any new messages. Below is my test setup in a pawn blueprint.

 

 



- Josh

 

 

----------------------------------------------------------------------------------------------------------------------------------------------

 

No worries glad this helped some people. I honestly spent forever looking as well. As far as the UDPReceiveWorker.h goes, that was something I was working on as to get the handling of receiving messages in another thread so the game does wait for a response. I never could get it to work properly.

UDPReceiveWorker.h 

Code:

#include "Networking.h"
#include "UDPNetworkingWrapper.h"
#include "NetworkingFunctionLibrary.h"
#include <string>



/**
 * This class holds the multi threading data for receiving UDP packets
 */
class VIRTUALTABLETOP_API UDPReceiveWorker : public FRunnable
{

	// Singleton instance, can access the thread at anytime.
	static UDPReceiveWorker* Runnable;

	// The data
	TArray<uint8>* ReceivedDataRef;

	/** Stop this thread? Uses Thread Safe Counter */
	FThreadSafeCounter StopTaskCounter;

	


public:
	UDPReceiveWorker(TArray<uint8>& ReceivedData, FSocket* InSocket, FTimespan& InWaitTime);
	virtual ~UDPReceiveWorker();



	// Begin FRunnable interface.
	virtual bool Init();
	virtual uint32 Run();
	virtual void Stop();
	// End FRunnable interface

	void EnsureCompletion();

	static UDPReceiveWorker* JoyInit(TArray<uint8>& ReceivedData, 
    FSocket* InSocket, FTimespan& InWaitTime);

/** Shuts down the thread. Static so it can easily be called from outside the thread context */
	static void Shutdown();

private:

	// Holds the network socket.
	FSocket* Socket;

	// Holds a pointer to the socket sub-system.
	ISocketSubsystem* SocketSubsystem;

	// Holds a flag indicating that the thread is stopping.
	bool Stopping;

	// Holds the thread object.
	FRunnableThread* Thread;

	// Holds the amount of time to wait for inbound packets.
	FTimespan WaitTime;

	
};

UDPReceiverWorker.cpp

Code:

include "VirtualTabletop.h"
#include "UDPReceiveWorker.h"

UDPReceiveWorker* UDPReceiveWorker::Runnable = NULL;

UDPReceiveWorker::UDPReceiveWorker(TArray<uint8>& ReceivedData, FSocket* InSocket, FTimespan& InWaitTime)
	: Socket(InSocket)
	, StopTaskCounter(0)
	, WaitTime(InWaitTime)
	, Stopping(false)
{

	const bool bAutoDeleteSelf = false;
	const bool bAutoDeleteRunnable = false;

	// Link the data
	ReceivedDataRef = &ReceivedData;

	SocketSubsystem = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM);
	Thread = FRunnableThread::Create(this, TEXT("UDPReceiveWorker"), 0, 
    TPri_BelowNormal); //windows default = 8mb for thread, could specify more

}

UDPReceiveWorker::~UDPReceiveWorker()
{
	delete Thread;
	Thread = NULL;
	SocketSubsystem = nullptr;
	Socket = nullptr;
	ReceivedDataRef = nullptr;
	//myNetworkingWrapper = nullptr;
}

// Init
bool UDPReceiveWorker::Init()
{
	return true;
}

//Run
uint32 UDPReceiveWorker::Run()
{
	TSharedRef<FInternetAddr> Sender = SocketSubsystem->CreateInternetAddr();

	while (!Stopping)
	{
		if (!Socket->Wait(ESocketWaitConditions::WaitForRead, WaitTime))
		{
			continue;
		}

		uint32 Size;

		while (Socket->HasPendingData(Size))
		{

			int32 Read = 0;
			Socket->RecvFrom(ReceivedDataRef->GetData(), ReceivedDataRef->Num(), Read,
            *Sender);

		}

	}

	

	return 0;
}


// Stop
void UDPReceiveWorker::Stop()
{
	StopTaskCounter.Increment();
}

UDPReceiveWorker* UDPReceiveWorker::JoyInit(TArray<uint8>& ReceivedData, FSocket* InSocket, 
FTimespan& InWaitTime)
{
	//Create new instance of thread if it does not exist
	//		and the platform supports multi threading!
	if (!Runnable && FPlatformProcess::SupportsMultithreading())
	{
		Runnable = new UDPReceiveWorker(ReceivedData, InSocket, InWaitTime);
	}
	return Runnable;
}

void UDPReceiveWorker::EnsureCompletion()
{
	Stop();
	Thread->WaitForCompletion();
}

void UDPReceiveWorker::Shutdown()
{
	if (Runnable)
	{
		Runnable->EnsureCompletion();
		delete Runnable;
		Runnable = NULL;
	}
}

//
//bool UDPReceiveWorker::IsThreadFinished()
//{
//	if (Runnable) return Runnable->IsFinished();
//	return true;
//}

If you get this working please share with us.

 

--------------------------------------------------------------------------------------------

 

 

=================================

=================================

=================================

 

 

출처: http://cafe.naver.com/unrealenginekr/411

 

 

언리얼 사용중에 궁금한 사항이 생겨서 질문 올립니다.

 

 

다름이 아니라, 언리얼에 내장되있는 네트워크 말고 LOW SOCKET 이나, C++ Library 이용한 소켓 프로그래밍을 할수있는 방법이

 

존재하는지 궁금하네요.

 

보통 상용게임 제작시에, 자체 네트워크 모듈 만들어서 사용한다고하는데..

 

방법이 궁금합니다.. ㅠ 유니티의 경우는 C# Socket 클래스 OR C# DLL 을 이용한 네트워크 프로그래밍이 가능한것으로 보아..

 

언리얼도 분명히 방법이 있을거같은데..

이부분에 대해서 조언좀 부탁드립니다. 감사합니다..

 

시니어멤버  

물론 방법은 존재합니다.^^

아래 link 참고해 주시고요~ 

 

http://cafe.naver.com/igc123/152

http://cafe.daum.net/igc123/K3VE/121

 

위 link 방법 말고도, 

unreal engine이 제공하는 FSocket을 이용하시거나,

class APlayerController와 님이 만든 win socket(또는 unix socket)을 

직접 연결해서 제어하는 것도 좋을 듯 싶네요.

(물론, 이건 동기화에 자신이 있으실 때, 그렇게 하시라는 겁니다.^^;;;)

 

 

 

근데.. 링크가 전부다 정회원 되야지 볼수있는 글이네요;;;

혹시 FSocket 사용 예제가 나온곳이 없을까요?

 

가입하시면, 승인 없이 바~로~ 보실 수 있습니다.
내키지 않으시면, 
바~로~ 탈퇴하셔도 되고요.^^;;;

soruce는 기술이 노출되는 거라서, 곤란하고요.^^;;;

 

뽀까뽀까 그렇군요~ 감사합니다.^^ 
뭐 사용이야 해보면 어찌 되겠죠..헤헤~

2014.04.21. 16:34

FSocket 자체가 플랫폼 별로 저수준 소켓을 감싸놓은 클래스에요. 보통 PC 기반 온라인 게임 

같은 경우 플랫폼을 

고려할 필요가 없으니까 그냥 WinAPI IOCP 같은 걸로 직접 구현하고 말죠. 플랫폼 독립적으로

 C++ 네트워크 라이브러리를 사용하는 방식으로 사용하고 싶으시면 이렇게도 가능합니다. 

언리얼 3 기준인데 잘되는거 제가 확인 했어요.

 

1. 각 플랫폼 별 boost asio 네트워크 라이브러리 준비 및 설치

 -  pc, mac, ios, 안드로이드 모두 boost 라이브러리 빌드하고 프로젝트에 추가 시켜 줍니다. 

다른 플랫폼은 문제가 안되는데 안드로이드가 좀 까다로워요.

2. boost asio를 사용해서 프로그래밍한다. 예제는 많아요. boost 포럼의 샘플 코드 보시면 됩니다.

 

FSocket 사용 예제는 제가 하나 만들어서 올리고 싶은데 시간이 안나서 ㅠㅠ

2014.04.21. 17:08

언리얼엔진4의 경우: 그냥 C++ socket을 쓰시면 됩니다.

언리얼엔진3의 경우: 언리얼 스크립트 네이티브 바인딩을 쓰는 방법이 있습니다. 

 

프라우드넷의 경우 언리얼엔진3의 언리얼스크립트를 이미 지원합니다.

언리얼엔진4는 아직 적용해보지는 않았지만 프라우드넷은 이미 iOS와 Android상에서 C++로 쓸 수 있으므로 

쓸 수 있을 가능성이 큽니다.

 

 

오~ 유명한 분 오셨네요~ ^^

 

 

=================================

=================================

=================================

 

 

출처: http://cafe.naver.com/unrealenginekr/8353

 

언리얼엔진4.0 Socket 통신, PC, IOS, Android 다른 클라이언트 통신 궁금한점

 

안녕하세요 언리얼 엔진에 관심을 갖고 있는 초보 입니다 ^^

 

언리얼 소켓 통신쪽을 보고있는데 

 

https://wiki.unrealengine.com/TCP_Socket_Listener,_Receive_Binary_Data_From_an_IP/Port_Into_UE4,_(Full_Code_Sample)

 

부분 예제가 나오더군요.

 

여기서 궁금한건 이 예제의 통신방법이 pc, ios, android 등등 기기들에 모두 적용이 되는건지,

 

이 예제로 안된다면 다른 방법으로 한번에 모두 적용할 방법은 없는지 알고 싶습니다. 

 

 

소중한 답변 부탁드립니다~!

-------------------------------------------------------------------------

답변

 

  • 인터넷 프로토콜은 국제 규약입니다.
    운영체제가 바뀐다고 해서 달라지지 않습니다.

    FSocket은 멀티 플래폼 처리가 되어 있는 것으로 알고 있습니다.
  • alrepond
    2016.02.17. 22:50답글답변 감사합니다 ^^
  • 수정|삭제

 

 

=================================

=================================

=================================

 

 

출처: https://wiki.unrealengine.com/TCP_Socket_Listener,_Receive_Binary_Data_From_an_IP/Port_Into_UE4,_(Full_Code_Sample)

 

TCP Socket Listener, Receive Binary Data From an IP/Port Into UE4, (Full Code Sample)

Contents

 [hide

Overview

Author: Rama (talk)

Dear Community,

In this tutorial I am giving you the code I used to enable a python script to communicate with UE4 over a TCP socket!

That's right!

I am just straight up giving you my whole source code that I spent the past several hours writing!

Rama

 

 

Build.CS

You will need at least this to work with sockets in UE4

PublicDependencyModuleNames.AddRange(new string[] { 
		"Core", 
		"CoreUObject", 
		"Engine", 
		"InputCore",
 
		"Sockets","Networking"
});

#include <string>

You will also need std::string !

You have to add include line for external symbols after PCH and before corresponding header with source.

example:

// MyClass.cpp
#include "MyProject.h"
#include <string>
#include "MyClass.h"

.h

#include "Networking.h"
 
//AYourClass definition
 
public:
 
FSocket* ListenerSocket;
FSocket* ConnectionSocket;
FIPv4Endpoint RemoteAddressForConnection;
 
bool StartTCPReceiver(
	const FString& YourChosenSocketName,
	const FString& TheIP, 
	const int32 ThePort
);
 
FSocket* CreateTCPConnectionListener(
	const FString& YourChosenSocketName,
	const FString& TheIP, 
	const int32 ThePort, 
	const int32 ReceiveBufferSize = 2*1024*1024
);
 
//Timer functions, could be threads
void TCPConnectionListener(); 	//can thread this eventually
void TCPSocketListener();		//can thread this eventually
 
 
//Format String IP4 to number array
bool FormatIP4ToNumber(const FString& TheIP, uint8 (&Out)[4]);
 
//Rama's StringFromBinaryArray
FString StringFromBinaryArray(const TArray<uint8>& BinaryArray);

.cpp

void AYourClass::Laaaaaauuuunch()
{
                                        //IP = 127.0.0.1, Port = 8890 for my Python test case
	if( ! StartTCPReceiver("RamaSocketListener", "127.0.0.1", 8890))
	{
		//UE_LOG  "TCP Socket Listener Created!"
		return;
	}
 
	//UE_LOG  "TCP Socket Listener Created! Yay!"
}
 
//Rama's Start TCP Receiver
bool AYourClass::StartTCPReceiver(
	const FString& YourChosenSocketName,
	const FString& TheIP, 
	const int32 ThePort
){
	//Rama's CreateTCPConnectionListener
	ListenerSocket = CreateTCPConnectionListener(YourChosenSocketName,TheIP, ThePort);
 
	//Not created?
	if(!ListenerSocket)
	{
		GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("StartTCPReceiver>> Listen socket could not be created! ~> %s %d"), *TheIP, ThePort));
		return false;
	}
 
	//Start the Listener! //thread this eventually
	GetWorldTimerManager().SetTimer(this, 
		&AYourClass::TCPConnectionListener, 0.01, true);	
 
	return true;
}
//Format IP String as Number Parts
bool AYourClass::FormatIP4ToNumber(const FString& TheIP, uint8 (&Out)[4])
{
	//IP Formatting
	TheIP.Replace( TEXT(" "), TEXT("") );
 
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//						   IP 4 Parts
 
	//String Parts
	TArray<FString> Parts;
	TheIP.ParseIntoArray( &Parts, TEXT("."), true );
	if ( Parts.Num() != 4 )
		return false;
 
	//String to Number Parts
	for ( int32 i = 0; i < 4; ++i )
	{
		Out[i] = FCString::Atoi( *Parts[i] );
	}
 
	return true;
}
//Rama's Create TCP Connection Listener
FSocket* AYourClass::CreateTCPConnectionListener(const FString& YourChosenSocketName,const FString& TheIP, const int32 ThePort,const int32 ReceiveBufferSize)
{
	uint8 IP4Nums[4];
	if( ! FormatIP4ToNumber(TheIP, IP4Nums))
	{
		VShow("Invalid IP! Expecting 4 parts separated by .");
		return false;
	}
 
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
	//Create Socket
	FIPv4Endpoint Endpoint(FIPv4Address(IP4Nums[0], IP4Nums[1], IP4Nums[2], IP4Nums[3]), ThePort);
	FSocket* ListenSocket = FTcpSocketBuilder(*YourChosenSocketName)
		.AsReusable()
		.BoundToEndpoint(Endpoint)
		.Listening(8);
 
	//Set Buffer Size
	int32 NewSize = 0;
	ListenSocket->SetReceiveBufferSize(ReceiveBufferSize, NewSize);
 
	//Done!
	return ListenSocket;	
}
//Rama's TCP Connection Listener
void AYourClass::TCPConnectionListener()
{
	//~~~~~~~~~~~~~
	if(!ListenerSocket) return;
	//~~~~~~~~~~~~~
 
	//Remote address
	TSharedRef<FInternetAddr> RemoteAddress = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
	bool Pending;
 
	// handle incoming connections
	if (ListenerSocket->HasPendingConnection(Pending) && Pending)
	{
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		//Already have a Connection? destroy previous
		if(ConnectionSocket)
		{
			ConnectionSocket->Close();
			ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(ConnectionSocket);
		}
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
		//New Connection receive!
		ConnectionSocket = ListenerSocket->Accept(*RemoteAddress, TEXT("RamaTCP Received Socket Connection"));
 
		if (ConnectionSocket != NULL)
		{
			//Global cache of current Remote Address
			RemoteAddressForConnection = FIPv4Endpoint(RemoteAddress);
 
			//UE_LOG "Accepted Connection! WOOOHOOOO!!!";
 
			//can thread this too
			GetWorldTimerManager().SetTimer(this, 
				&AYourClass::TCPSocketListener, 0.01, true);	
		}
	}
}
 
//Rama's String From Binary Array
//This function requires 
//		#include <string>
FString AYourClass::StringFromBinaryArray(const TArray<uint8>& BinaryArray)
{
	//Create a string from a byte array!
	std::string cstr( reinterpret_cast<const char*>(BinaryArray.GetData()), BinaryArray.Num() );
	return FString(cstr.c_str());
}
 
//Rama's TCP Socket Listener
void AYourClass::TCPSocketListener()
{
	//~~~~~~~~~~~~~
	if(!ConnectionSocket) return;
	//~~~~~~~~~~~~~
 
 
	//Binary Array!
	TArray<uint8> ReceivedData;
 
	uint32 Size;
	while (ConnectionSocket->HasPendingData(Size))
	{
		ReceivedData.Init(FMath::Min(Size, 65507u));
 
		int32 Read = 0;
		ConnectionSocket->Recv(ReceivedData.GetData(), ReceivedData.Num(), Read);
 
		//GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("Data Read! %d"), ReceivedData.Num()));
	}
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
	if(ReceivedData.Num() <= 0)
	{
		//No Data Received
		return;
	}
 
	VShow("Total Data read!", ReceivedData.Num() );
	GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("Data Bytes Read ~> %d"), ReceivedData.Num()));
 
 
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//						Rama's String From Binary Array
	const FString ReceivedUE4String = StringFromBinaryArray(ReceivedData);
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 
	VShow("As String!!!!! ~>",ReceivedUE4String);	
	GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("As String Data ~> %s"), *ReceivedUE4String));

Core Research I Am Sharing with You

The hardest part of this whole process for me was converting the received binary data into UE4's FString format!

I wrote this function to do it, which adds the null terminator and everything, and uses the strong backbone of std::string!

//Rama's String From Binary Array
//This function requires 
//		#include <string>
FString AYourClass::StringFromBinaryArray(const TArray<uint8>& BinaryArray)
{
	//Create a string from a byte array!
	const std::string cstr( reinterpret_cast<const char*>(BinaryArray.GetData()), BinaryArray.Num() );
 
	//FString can take in the c_str() of a std::string
	return FString(cstr.c_str());
}

How It Works

The first socket listens on the port and IP supplied, and if a connection is received on this port, then the actual ListenerSocket is created.

The ListenerSocket is run in very short looping timer of 0.01 seconds.

You could also use a thread for this :)


Rama's Tutorial on Multi-Threading, Create Threads in UE4


Whenever the ListenerSocket receives data, it makes sure to gather all of it using the while loop, and then I convert the results into a FString.

//Binary Array!
TArray<uint8> ReceivedData;
 
uint32 Size;
while (ConnectionSocket->HasPendingData(Size))
{
	ReceivedData.Init(FMath::Min(Size, 65507u));
 
	int32 Read = 0;
	ConnectionSocket->Recv(ReceivedData.GetData(), ReceivedData.Num(), Read);
 
	//GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("Data Read! %d"), ReceivedData.Num()));
}

If you are not receiving string data you can skip that part and just pass out the binary array itself :)

Another TCP Source Code, by Alfalfasprossen

Community member AlfalfaProssen is generously sharing his own ongoing TCP plugn, check back over time to see how it is developing!

Thanks Alfalfasprossen!

Alfalfa's TCP Plugin

 

 

=================================

=================================

=================================

 

 

 

출처ㅣ http://cafe.naver.com/unrealenginekr/5796

 

https://wiki.unrealengine.com/TCP_Socket_Listener,_Receive_Binary_Data_From_an_IP/Port_Into_UE4,_(Full_Code_Sample)

 

 

를 참고해서 테스트를 해보려고 하는데,

#include <string>

부터 인식을 못하고 있네요... ㅠ

 

cpp 파일의 가장 위쪽에 쓰라고 하는데도 인식을 못하고

다른 cpp 파일의 windows socket 예제를 가져와서 하려고해도

라이브러리를 인식을 못해서 구현도 못하네요...

 

UE4로 하려고 하는데 제약이 너무 많아서

이젠 걍 포기해야하나 싶고 1달넘게 고생해도 안되니 넘 힘드네요 ㅠㅠ

 

-------------------------------------------------------------------------------------------

 

 

  • 제일 위가 아니라
    미리 컴파일된 헤더 밑에, 
    소스에 대응하는 헤더 위에 작성해야 합니다.

    // MyClass.cpp
    #include "MyProject.h" // PCH
    #include <string>
    #include "OtherClass.h"
    #include <OtherStd.h>
    #include "MyClass.h"
      나가놀자
    2015.08.11. 17:19답글위키도 수정했습니다.
  •  
  • 신고
  •   라테르
    2015.08.26. 15:47답글답변 감사합니다! 직접 작성하신 분이셨군요!!

    지금 계속 해보고 있긴한데, 오류가 떠서 힘드네요 ㅠ
    VShow는 클라이언트 메시지여서 일단 주석처리했구요,
    문제는 GetWorldTimerManager().SetTimer에서 
    error C2228: left of '.SetTimer' must have class/struct/union
    error C3861: 'GetWorldTimerManager': identifier not found

    두가지 에러가 뜨는데,
    https://docs.unrealengine.com/latest/INT/Programming/UnrealArchitecture/Timers/index.html

    여기를 참고해서 
    FTimerDelegate::CreateUObject 를 이용해서 수정해도 되지가 않네요.. ㅠ
    버전업이 되어서 달라져서 그런지 계속 되지가 않습니다 ㅠㅠ
  • 신고
  •   나가놀자
    2015.08.26. 16:27답글라테르 작성은 라마라는 분이 하신거고
    인클루드 부분만 수정했습니다.
    https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/FTimerManager/SetTimer/4/index.html
  • 신고
  •   기메경
    2015.08.13. 10:09답글
    저도 윈도우소켓을 언리얼로 이식할려다가 충돌땜에 고생좀했는데
    좀만 하다보면 별거아니에용 힘내세용 ㅜ
  • 신고
  •   빅캣
    2015.12.24. 11:09답글ㅋ 저도 이거 해보고 있는데. 컴파일까지 됐다고 뜨는데... 그 이후로 뭘해야 하는지 모르겠어요.
    Player Controller 라서 Actor나 캐릭터 밑에 두고 실행하면 접속이 안된다는 메세지라도 뜨는거 아닌가요?
    아무리 플레이를 눌러봐도 아무런 현상이 나타나지 않네요...
  • 신고

 

=================================

=================================

=================================

 

 

출처: http://mypi.ruliweb.daum.net/mypi.htm?id=pokapoka&num=8230

 

Question>

질문1:
UDK remote를 사용하려고 하는데, 
UDK가 설치된 PC의 IP 주소를 입력해도 찾지를 못함.
UDK가 설치된 PC를 UDK remote가 인지하려면, 어떻게 해야 하는가?

질문2:
unreal로 client/server 기반의 network play가 되는 app을 만들었음.
server는 windows에서 작동되고, client는 iOS 기기에서 작동됨.
client app을 unreal frontend로 다수의 iOS 기기에 전송했음.
그런데, server를 인지하지 못함.
client app이 server를 인지하려면, 어떻게 해야 하는가?

-------------------------------------------------------------

Answer>

위 질문들의 공통적인 문제점은 '방화벽'입니다.^^;;;;;;;;
unreal app이 통신을 하려면, 
'방화벽'에 대한 설정 해제가 선행되어야 합니다.

h/w적인 방화벽 해제는 
가지고 계신 공유기의 manual을 보시고, 
허용하도록 설정하시면 됩니다.

그리고,
unreal app와 PC의 network 연결이 필요할 경우,
s/w적인 방화벽 해제가 추가적으로 더 필요합니다.
운영체제와 vaccine 모두 다 해당됩니다.

한가지 더 알아 두셔야 할 것은
UDK 2013년 7월 version 기준으로 
IPv6는 아직도 지원되지 않기 때문에,^^;;;;;;;
app의 통신은 IPv4로 하셔야 하고,
방화벽의 설정과 해제도 IPv4를 기준으로 하셔야 합니다.^^;;;;;;

Tag:
안기훈, Kee Hoon Ahn, Unreal, UDK, iPhone, iPad, app, 앱, iOS

 

 

=================================

=================================

=================================

 

 

 

출처: http://mypi.ruliweb.daum.net/mypi.htm?id=pokapoka&num=7988

 

Question>

unreal engine으로 network game 만들려면?

-------------------------------------------------------------

Answer>

아래 link 주로 보시면서, 만드시면 되고요.^^

http://udn.epicgames.com/Three/ReplicationHomeKR.html

간단하게 요약해서 보신다면, 아래 link 보세요.^^;;;;

http://forums.epicgames.com/threads/757312-Launching-game-with-server-client-support

기본적으로 제공하는 network mode를 진입하는 방법은 아래 3가지 입니다.

listen server 
 => 'open MapName?Listen' 또는 'udk MapName?Listen'으로 시작합니다.
 
dedicated server 
 => 'udk server MapName'으로 시작합니다.
 
client 
 => 'open [ipaddress]' 또는 'udk [ipaddress]'으로 시작합니다.

network 기능이 내장되기는 했지만, 
제작자가 s!crip로 짜서 연결해 줘야 하는 부분들이 제법 됩니다.^^;;;;;

그리고, 
UDK의 iOS용 app을 만들 경우, network 기능 제약이 심합니다.

- IPv6 사용 불가. ^^;;;
- UDP 사용 불가. -_-;;;;;;
- 특정 상태에서만 listen socket 생성 가능. -_-+

iOS용 UDK로 FPS/TPS가 아닌 network game을 만들려면, 
full license의 unreal engine을 구입해서 
core의 objective-C 부분을 수정하시던가, 
아니면, 
우회적인 방법을 사용해서, 
기능을 확장하는 수 밖에 없습니다. -_-+


 

=================================

=================================

=================================

 

 

출처: http://cafe.naver.com/unrealenginekr/6996

 

윈도우 콘솔어플리케이션으로 udp 에코 서버를 만들어놓고, 언리얼 프로젝트로 클라이언트를 만들려고 합니다.

서버에서 데이터를 받은 것은 확인되었으나 다시 돌려주는 데이터를 언리얼 프로그램에서 받지 못하는 것 같습니다.

아래에 정돈되진 않았지만 코드 올려봅니다.

 

void AMyActor::BeginPlay() {
    Super::BeginPlay();
    myText->SetText(TEXT("Hello"));
    FSocket* mySocket = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateSocket(NAME_DGram, TEXT("create mySocket"), false);
    TSharedRef<FInternetAddr> serverAddress = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
    FIPv4Address ip;
    FIPv4Address::Parse(TEXT("127.0.0.1"), ip);
    serverAddress->SetIp(ip.GetValue());
    serverAddress->SetPort(4444);
    FString serialized = TEXT("myText");
    uint8* recvd = nullptr;
    TCHAR* serializedChar = serialized.GetCharArray().GetData();
    int32 size = FCString::Strlen(serializedChar);
    int32 sent = 0;
    mySocket->SendTo((uint8*)TCHAR_TO_UTF8(serializedChar), size, sent, *serverAddress);
    mySocket->RecvFrom(recvd, size, sent, *serverAddress);
    myText->SetText((FString)UTF8_TO_TCHAR(recvd));
}

 

헤더에는 UTextRenderComponent* myText; 한 줄 작성했습니다.

혹시 FSocket 통신 방법에 대한 예제나 튜토리얼 작성해주실 수 있는 분 계시다면 꼭 좀 부탁드리겠습니다.

인터넷으로 안찾아본 곳이 없을 정도로 다 검색해봤는데 너무 정보가 없어서 개념 잡기도 어렵고 며칠째 고생하고 있습니다.

 

--------------------------------------------------------------------------

 

 

  • 저도..소캣프로그래밍은 안해봤지만..
    mySocket->RecvFrom(recvd, size, sent, *serverAddress);
    이부분에서..
    ServerAddress 로 부터 값을 받아오는건가요 ?
    음.. 루프백 이니까 르럴수도 있겠네요..

    근데 .. 함수가 비긴 플레이인데 플레이 시작하면 딱 한번 실행되고 끝이잖아요? 
    Recv 는 뭔가 기다려야할것같은 함수인데
    샌드를 보내고 리시브를 받기까지 시간이 약간 걸릴텐데
    그 과정을 무시하고 지나간게 아닐까요?
    Recv는 생각해봐두 쓰레드 만들어서 루프를 계속 돌면서 받아와야할것같은데 ㅎㅎ

  •   테디곰
    2015.11.18. 16:00답글음 그리고.. 저렇게 주소로 값을 직접 보내주지 마시구..
    서버니깐.. 바인드를 하면서 클라이언트가 접속될때까지 기다린후
    소캣을 어셉트 하셔서 통신하는게 더 안정적일것 같은데요 ~
    저렇게 하면 왠지 안될것같은 느낌이 드네요 ㅜㅜ

    저도 아직 학생이라 잘 모르지만..느낌이 이상하네요 ㅎㅎㅋ
  • 신고
  •   테디곰
    2015.11.18. 16:04답글그리고 소캣을 TCP소캣으로 만드셨는데
    에코서버는 UDP니깐 어떻게보면 당연히 데이터를 못받는게 맞을수도..
  • 신고
  •   테디곰
    2015.11.18. 16:05답글ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateSocket(NAME_DGram, TEXT("create mySocket"), false);

    부분에서 UDP서버로 만들어보세요..
    뒤에 false 를 true로 주면 UDP서버가 된다고는 하는뎅..ㅎㅎ그럼 서로 통신이 되지않을까요
  • 신고
  •   건전한학생
    2015.11.23. 10:11답글테디곰 답변 감사합니다.
    RecvFrom은 제가 scanf 같이 기다려서 값을 받아오는 거라고 생각했는데, 윈속에선 그런식으로 동작했거든요. 멀티쓰레딩은 아직 해본적이 없어서 하려면 조금 복잡해지겠네요 ㅠㅠ
    그리고 UDP는 TCP와 다르게 listen과 accept 과정이 없어요.
    ISocketSubsystem으로 소켓을 생성하는 부분에서는 첫번째 매개변수를 STREAM으로 주면 TCP 소켓이 만들어지고 DGram으로 주면 UDP가 만들어진다고 합니다.
    뒤에 false는 true로 줘봤는데 무슨 차이가 있는건지는 모르겠네요. 아무리 검색해봐도 설명해주는 곳이 없어서 뭐하는 건지 알 수가 없어요. 라이브러리에 "overrides any platform specific protocol with UDP instead"라고 한 줄 적혀있네요.
  • 신고
  •   테디곰
    2015.11.23. 13:24답글건전한학생 그렇군요 ~ 저도 좋은정보 알아갑니다 감사해용
  • 신고
  •   테디곰
    2015.11.23. 13:25답글건전한학생 굳이 멀티쓰레딩을 안해두
    저부분에서
    Recv size 값이 0보다 작거나 같을경우에 while문 돌려서
    잠시 루프를 도시는것도 괜찮을듯ㅎ
  • 신고
  •   빅캣
    2016.01.05. 17:17답글실례지만 이거 컴파일 후 플레이하면 프로그램이 다운 되던데, 혹시 셋팅 같은 것이 따로 있나요? 제가 쓴 버젼은 4.9 입니다
  • 신고
반응형

 

 

728x90

 

 

 

=================================

=================================

=================================

 

 

출처: https://wiki.unrealengine.com/TCP_Socket_Listener,_Receive_Binary_Data_From_an_IP/Port_Into_UE4,_(Full_Code_Sample)

FTimerManager::SetTimer

template<class UserClass>
void SetTimer
(
    FTimerHandle & InOutHandle,
    UserClass * InObj,
    typename FTimerDelegate::TUObjectMethodDelegate< UserClass >::FMethodPtr InTimerMethod,
    float InRate,
    bool InbLoop,
    float InFirstDelay
)

 

Remarks

Sets a timer to call the given native function at a set interval. If a timer is already set for this delegate, it will update the current timer to the new parameters and reset its elapsed time to 0.

Parameters

ParameterDescription

InOutHandle Handle to identify this timer. If it is invalid when passed in it will be made into a valid handle.
InObj Object to call the timer function on.
InTimerMethod Method to call when timer fires.
InRate The amount of time between set and firing. If <= 0.f, clears existing timers.
InbLoop true to keep firing at Rate intervals, false to fire only once.
InFirstDelay The time for the first iteration of a looping timer. If < 0.f inRate will be used.

Example Code

MyCharacter.cpp at line 97:

void AMyCharacter::ToggleTimer()  
{  
    UWorld* World = GetWorld();  
    if( World )  
    {  
        // If the timer has expired or does not exist, start it  
        if( ( SampleTimerHandle.IsValid() == false ) || ( bTimerExpired) )  
        {  
            World->GetTimerManager().SetTimer(SampleTimerHandle, this, &AMyCharacter::SampleTimerExpired, 10.0f);  
            bTimerExpired = false;  
        }     
        else  
        {         
            if( World->GetTimerManager().IsTimerPaused(SampleTimerHandle) == true )  
            {  
                World->GetTimerManager().UnPauseTimer(SampleTimerHandle);  
            }  
            else  
            {  
                World->GetTimerManager().PauseTimer(SampleTimerHandle);  
            }  
        }  

    }  
}  

void AMyCharacter::SampleTimerExpired()  
{  
    bTimerExpired = true;  
}  

MyCharacter.cpp at line 442:

 if (SampleTimerHandle.IsValid() == true)  
        {  
            UWorld* World = GetWorld();  
            float TimerTime = 0.0f;  
            if (World != nullptr)  
            {  
                if (bTimerExpired == true)  
                {  
                    TheHud->TimerText = FString::Printf(TEXT("Timer Has Expired"));  
                    TheHud->TimerTextColor = FColor::Red;  
                }  
                else  
                {  
                    if (World->GetTimerManager().IsTimerPaused(SampleTimerHandle) == true)  
                    {  
                        TheHud->TimerText = FString::Printf(TEXT("Current Time is %f - Timer Is Paused"), World->GetTimerManager().GetTimerRemaining(SampleTimerHandle));  
                        TheHud->TimerTextColor = FColor::Yellow;  
                    }  
                    else  
                    {  
                        TheHud->TimerText = FString::Printf(TEXT("Current Time is %f"), World->GetTimerManager().GetTimerRemaining(SampleTimerHandle));  
                        TheHud->TimerTextColor = FColor::Blue;  
                    }  
                }  
            }  
        }  
        else  
        {  
            TheHud->TimerText = TEXT("Timer Not Started");  
            TheHud->TimerTextColor = FColor::Blue;  
        }  
Module Engine
Header Runtime/Engine/Public/TimerManager.h

 

=================================

=================================

=================================

 

 

출처: http://cafe.naver.com/unrealenginekr/1108

 

소켓을 어떻게 쓰나 싶어서 찾아봤는데

 

언리얼 공홈 위키에 쓰여진 FSocket 사용법이 안되네요.

 

4.2.1 사용하구요.

 

FSocket* Socket = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateSocket(NAME_Stream, TEXT("default"), false);

 

일단 

ISocketSubsystem::Get이랑

 

PLATFORM_SOCKETSUBSYSTEM이 없는건지 뭔지 코드힌트에 안나옵니다.

 

FIPv4Address 클래스도 안나오네요.

 

당연히 빌드도 안됨.

 

C++은 기초를 배우는 중이라 따로 C++로 소켓 만들 줄도 모르네요.

 

----------------------------------------------------------------------------------------------

FSocket 해결 하셨나여??? 저도 똑같은 문제가 뜨는데
헤더에
#include "Engine.h"
#include "Runtime/Networking/Public/Interfaces/IPv4/IPv4Address.h"
#include "Runtime/Sockets/Public/SocketSubsystem.h"
#include "Runtime/Core/Public/Templates/SharedPointer.h"
#include "Runtime/Sockets/Private/BSDSockets/SocketsBSD.h" 
#include "Runtime/Sockets/public/Sockets.h"

 

다 추가했습니다... 혹시 어떻게 해결하셨나여

--------------------------------------------------------------------

음...소스코드상에 있는데요..소스코드에서 검색해 보셨나요? 혹시 사용하시는 곳에서 인클루드 안 하신거 아닌가 하는...

 

>ISocketSubsystem클래스를 포함하는 헤더를 인클루드하면 무수한 에러가 뜨네요.(이미 기본적으로 인클루드 되어있는 듯) 공홈 API문서 상의 FIPv4Address클래스를 포함하는 헤더의 경로도 실제 소스상에는 없는 경로....

 

>Networking\Public\Interfaces\IPv4\IPv4Address.h 여기 있네요. 소스코드로 작업하실 때는 소스코드를 검색해 보시는 게 제일 빨라요. 공홈 어딘지는 모르겠으나 소스코드는 바뀔 수도 있고, 도큐먼트에 바로바로 반영될 순 없습니다.

 

>왕리얼짱 아 경로는 제가 잘못봤네요;; 거기 있는게 맞군요. 그래도 ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM) 이부분이 작동이 안되서 말이죠;;;

 

------------------------------------------------------------------------------

 

아래 file이 있는 지 확인 해 보세요.

 

[UE4 root]\Engine\Source\Runtime\Sockets\Public\SocketSubsystem.h

 

없을 리가 없죠.^^;;;

 

네 있습니다;;

 

-------------------------------------------------------------------------

 

1. [프로젝트명].Build.cs

사용할 모듈 이름 추가

--> 

PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "Networking", "Sockets" });

 

2. [클래스명].h

모듈 헤더 추가

--> 

#include "Engine.h"

#include "Networking.h"

#include "Sockets.h"

#include "SocketSubsystem.h"

 

BP 에서 사용한다면 노출시킬 함수에 매크로 설정

-->  

UFUNCTION(BlueprintCallable, Category = Socket)

 void ConnectToServer();

 

3. [클래스명].cpp

코드 구현

-->

 FSocket* Socket = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateSocket(NAME_Stream, TEXT("default"), false);

 

 FString address = TEXT("127.0.0.1");

 int32 port = 8989;

 FIPv4Address ip;

 FIPv4Address::Parse(address, ip);

 

 TSharedRef<FInternetAddr> addr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();

 addr->SetIp(ip.GetValue());

 addr->SetPort(port);

 

 GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("Trying to connect.")));

 

 bool connected = Socket->Connect(*addr);

 

 

 

>

 

 

=================================

=================================

=================================

 

 

 

출처: http://www.kirurobo.com/2015/12/ue4-udp.html

 

はじめに

モーションキャプチャ装置のデータを受信するプラグインを作りました
その時の核となったUDP受信あたりの手順を残しておきたいと思います。

扱ったモーションキャプチャ装置について

Perception Neuron や、その先輩(ライバル)的存在の MVN といったモーションキャプチャ装置があります。

これらのモーションキャプチャのソフト(Axis Neuron / MVN Studio)はもちろん記録もできますが、ネットワーク経由でデータを送る仕組みを持っています。
このデータを受信できれば、基本的にはどんなソフトでもリアルタイムにモーションを参照することができます。

Perception Neuron はどこのご家庭にもあるそうですが、私の身近にあったのは MVN でした。しかし、Unreal Engine 4 用のプラグインはメーカー曰く出す予定は今の所無いそうでしたので、自作することにしました。
そのうち Perception Neuron でも同じようにデータがUDPで送れることが分かったため、ついででそちらにも対応させてみました。

UDPについて

Perception Neuron は TCP と UDP という2種類の方法でデータを送信できますが、MVN は UDP でしたので、それを使うこととしました。
ざっくり言うと下記のような違いかと思います。

  • TCP … 電話みたいな通信のイメージ。相手がちゃんと聞いているか確認しつつデータを送る。
  • UDP … TVみたいな放送、あるいは郵便のイメージ。一方的に送り付ける。途中で消えたり順番が入れ替わったりもする。

それぞれ利点や欠点はありますが、リアルタイムモーションキャプチャの用途だと、完全でなくても即時性が大事なので UDP の方が向いていると個人的には思います。(でも Perception Neuron は TCP の方を主に作ってあるみたい。UDP の実装を改善してほしい点が幾つかあったり…)

さしあたり私が扱ったのは UDP で受信する部分のみです。
図で書くとこんな感じで一方向です。

 

モーションデータ送信と受信

なお、受信側ではデータが正しければ送信元が何かは関係ありません。
そこでKinect から MVN のふりをしてデータを送る側のソフトも作りましたが、それについては別の機会にでも。

Unreal Engine 4 での UDP 受信

UE4は普通に作ったものをベースにプラグイン化できるようなので、「プラグインにする」という点はまず考えず、UDP受信を行おうと、ネットで資料を探しました。

といった記事を拝見したりした結果、「FSocket」「FUdpSocketBuilder」を使えばいいのかなー、というところまでは見当をつけました。

が、それを使おうとするまでで若干ハマりました。

#includeするまで

 

1
2
#include "Networking.h"
#include "Sockets.h"

が必要だと思ったのですが、そのままでは includeの候補に出ていませんし、書いてもビルドできません。

 

下記の手順が必要でした。

  1. (プロジェクト名).Build.cs というファイルがあるので、そこの PublicDependencyModuleNames.AddRange() に “Networking”, “Sockets” を追加
  2. Visual Studio を一旦閉じ、「Visual Studio プロジェクトを更新」してから再度開く

 

 

ここできちんと更新できていないと、#includeできずに混乱しました。
正しく更新できていれば #include で候補が出てきます。
場合によってはビルドも必要だったかもしれません。

 

FUdpSocketBuilder の利用

私は #include まででしばらく詰まりましたが、それができれば FUdpSocketBuilder を使っている例を調べて、コードは大体すんなり書けた気がします。
Mac でも Android でも同じコードで動いて素晴らしいです。

役にたつかわかりませんが簡単なUDP受信(受信サイズを得るだけ)の例を置いてみます。
GameInstance を継承した下記クラスを作って、プロジェクト設定の GameInstance に指定すると勝手に受信を行ってログに出力します。

UdpReceiveGameInstance.h

 

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


#pragma once


#include "Engine/GameInstance.h"
#include "Networking.h"
#include "Sockets.h"
#include "UdpReceiveGameInstance.generated.h"


/**
 * 起動時からUDP受信を行うGameInstance
 */
UCLASS()
class UDPSAMPLE_API UUdpReceiveGameInstance : public UGameInstance
{
    GENERATED_BODY()


    virtual void Init() override;
    virtual void Shutdown() override;


    FSocket *m_Socket;
    FUdpSocketReceiver *m_Receiver;


    /* UDPデータが届いた際に呼ばれるコールバック */
    void UdpReceivedCallback(const FArrayReaderPtr& data, const FIPv4Endpoint& ip);
    
public:
    /* UDP待ち受けポート番号 */
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "UDP")
        int32 Port = 7001;


    /* ポートを開いて受信待ちにします */
    UFUNCTION(BlueprintCallable, Category = "UDP")
        bool Connect();


    /* ポートを閉じて受信を終了します */
    UFUNCTION(BlueprintCallable, Category = "UDP")
        void Close();
};

UdpReceiveGameInstance.cpp

 

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


#include "UdpSample.h"
#include "UdpReceiveGameInstance.h"


/* 起動時の初期化処理 */
void UUdpReceiveGameInstance::Init()
{
    /* 最初から自動で接続してしまう */
    this->Connect();
}


/*  終了時の処理 */
void UUdpReceiveGameInstance::Shutdown()
{
    /* ポートを閉じる */
    this->Close();
}


/* ポートを開き受信開始 */
bool UUdpReceiveGameInstance::Connect()
{
    if (m_Socket == NULL) {
        m_Socket = FUdpSocketBuilder(TEXT("Mocap UDP socket"))
            .BoundToPort(this->Port)
            .Build();
    }


    if (m_Socket != NULL) {
        /* UDP受信を開始 */
        m_Receiver = new FUdpSocketReceiver(m_Socket, FTimespan(0, 0, 1), TEXT("UDP receiver"));
        m_Receiver->OnDataReceived().BindUObject(this, &UUdpReceiveGameInstance::UdpReceivedCallback);


        // 接続成功
        UE_LOG(LogTemp, Log, TEXT("Connected to UDP port %d"), this->Port);
        return true;
    }


    // 接続失敗
    UE_LOG(LogTemp, Warning, TEXT("Could not open UDP port %d"), this->Port);
    return false;
}


/*  受信を終了してポートを閉じる */
void UUdpReceiveGameInstance::Close()
{
    if (m_Receiver != NULL) {
        m_Receiver->Exit();
        delete m_Receiver;
        m_Receiver = NULL;
    }


    if (m_Socket != NULL) {
        m_Socket->Close();
        delete m_Socket;
        m_Socket = NULL;
    }
}


/*  UDPでデータが届いた際のコールバック */
void UUdpReceiveGameInstance::UdpReceivedCallback(const FArrayReaderPtr& data, const FIPv4Endpoint&)
{
    uint32 receivedSize = data->GetAllocatedSize();
    UE_LOG(LogTemp, Log, TEXT("%d bytes received!"), receivedSize);
}

上記コードでは肝心のデータ解釈がありませんが、それは送られてくるデータの仕様による話になってきます。(もしニーズがあればまた書くかも)

その他 UE4 の C++ コーディングではまったところ

エラーの場所がわからない

Visual Studio でビルド時にエラーが出た場合、「エラー一覧」を見ても原因がわからなかったりしました。
「出力」を見るとわかりやすかったです。
Visual Studio というよりUEのツール がメッセージを出してくれていますので。

コメントに日本語を入れるとトラブル

Visual Studio で開くファイルはそのままだと Shift JIS になりました。
Shift JIS であれば // のコメントも普通に書けました。

ただ、UEエディタでは関数やプロパティに書いたコメントをマウスオーバーで表示してくれますが、Shift JIS では文字化けしていました。
かといってファイルの文字コードをそのまま UTF8 にすると、// のコメント部分でエラーになりました。

最終的に、日本語を含むコメントは常に /* */ を使い、ファイルはUTF8で保存することにしてみました。

終わりに

モーションキャプチャプラグインの話をしようと思っていたものの、UDP受信の話とか、はまった話がメインになりました。
当ブログは基本的に後輩に向けた資料のつもりで書いています。行なったことのメモ程度のものも今後増やしてみようかと思いますが、皆様のお役に立つかはわかりません (^^;

 

 

=================================

=================================

=================================

 

 

 

출처: http://cafe.naver.com/igc123/257

 

Question>

 

안녕하세요.

FSocket으로 서버접속후 서버가 죽거나 서버가 disconnect 시킬때를 감지려면 어떻게 해야 하나요?

 

현재 코드는 아래와 같습니다.

 

GEngine - > AddOnScreenDebugMessage(-1, 5. f, FColor::Red, FString::Printf(TEXT("Trying to connect.")));
ConnectionSocket = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM) - > CreateSocket(NAME_Stream, TEXT("default"), false);
FString address = TEXT("127.0.0.1");

int32 port = 6000;

FIPv4Address ip;
FIPv4Address::Parse(address, ip);
TSharedRef < FInternetAddr > addr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM) - > CreateInternetAddr();

addr - > SetIp(ip.GetValue());
addr - > SetPort(port);

bool connected = ConnectionSocket - > Connect( * addr);

if (connected)
{
    GEngine - > AddOnScreenDebugMessage(-1, 5. f, FColor::Red, FString::Printf(TEXT("Connect success.")));
} 
else
{
    GEngine - > AddOnScreenDebugMessage(-1, 5. f, FColor::Red, FString::Printf(TEXT("Connect fail.")));
}

 

접속은 잘되는데 서버를 죽였을때 어떻게 체크를 해야할까요?

 

-------------------------------------------------------------

 

Answer>

 

2가지 방법이 가능하겠습니다.

 

1>GetConnectionState()를 사용하는 방법.

아래 source 참고하시고요.

 

if( ESocketConnectionState::SCS_Connected == ConnectionSocket->GetConnectionState() )

{

  //server와 연결이 유효함.^^

}

else

{

  //server와 연결이 끊겼음.^^;;;

}

 

위와 같이 하시면, 접속차단을 감지할 수 있습니다.^^

 

 

 

2>class를 재정의해서 Close() 함수를 재정의하는 방법.

class FScokect을 상속 받은 님만의 class FYourSocket을 만드시고,

거기에 있는 Close()라는 함수를 호출시 님만의 특별한 처리를 할 수 있도록 재정의하세요.

 

bool FYourSocket::Close()

{

  //server와 연결이 끊겼음.^^;;;

}

 

위와 같이 하시면, 접속이 끊어졌을 때, 

Close()가 호출되서 바로 감지할 수 있습니다.^^

 

이 방법의 경우, class ISocketSubsystem의 일부( CreateSocket(), ... )와 

class FSocketSubsystem[목표 운영체제(windows, iOS, ...)]의 일부를 수정하셔야 가능합니다.

 

 

 

둘중에 하나 고르세요~ ^^

 

=================================

=================================

=================================

 

 

출처: http://cafe.naver.com/unrealenginekr/10451

 

https://wiki.unrealengine.com/Third_Party_Socket_Server_Connection

 

이거 참고해서 통신 모듈을 만들어 보고싶어서 시도해봤는데

FSocket* 의 Recv를 쓰면 데이터가 전송될 때까지 마냥 기다리는 것 같습니다.

어떻게 하면 될 지 궁금합니다

 

출처: https://wiki.unrealengine.com/Third_Party_Socket_Server_Connection

 

Third Party Socket Server Connection

Rate this Article:

5.00

 (2 votes)

Approved for Versions:(please verify)

We’ve been quietly working on our new game here at OSnap! Games and one of the features our new game will include is a lobby system where all players can chat among one another. The UE4 dedicated server is great for a game server but it’s overkill for something as simple as a chat server so we set out to get UE4 connecting to a third party socket server.

Contents

 [hide

Creating the Socket

The first step in getting UE4 connected to a third party server is initializing a socket.

 

FSocket* Socket = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateSocket(NAME_Stream, TEXT("default"), false);

 

The parameters are as follows

  1. Type
  2. Description
  3. ForceUDP

  In our case we're connecting using TCP so we've set ForceUDP to false.

 

Preparing the Address

The next part is getting the address you wish to connect to ready. Epic provides the tools to get this done quickly.

FString address = TEXT("127.0.0.1"); int32 port = 19834; FIPv4Address ip; FIPv4Address::Parse(address, ip); TSharedRef addr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr(); addr->SetIp(ip.GetValue()); addr->SetPort(port);

 

Now that your address is ready to go you simply have to tell UE4 to start the connection.

 

bool connected = Socket->Connect(*addr);

If connected is true you've successfully connected to your socket server!

 

Sending a Message

Alright, so you're connected but how do you send messages to it? A lot of that is up to you. Depending on your server there are different ways to serialize and send a message. The important part though is how does UE4 handle it.

First things first, we must prepare the message to be sent.

FString serialized = TEXT("loadPlayer|1"); TCHAR *serializedChar = serialized.GetCharArray().GetData(); int32 size = FCString::Strlen(serializedChar); int32 sent = 0;

 

What's going on in the above? We're sending a message to a socket server with the type "loadPlayer" and a single parameter of 1. What is happening in UE4 here is we're taking an FString, and turning it into a TCHAR*.

Finally, with the message formatted we can send it to our server!

 

bool successful = Socket->Send((uint8*)TCHAR_TO_UTF8(serializedChar), size, sent);

 

Sending data in UE4 requires it to be a uint8* and again, Epic provides the tools to get from TCHAR* to UTF8 which can be sent as a uint8*.

As far as reading data back from your socket server the key is in the functions HasPendingData and Recv of the FSocket class.

 

Dependency in Build.cs

One final thing to take note of. Inside your project's Build.cs file you'll need to add the "Sockets" package as a dependency in PublicDependencyModuleNames.

 

PublicDependencyModuleNames.AddRange( new string[] { "Core", "CoreUObject", "Engine", "Sockets" } );

Reposted from http://www.osnapgames.com/2014/05/24/connecting-to-a-third-party-socket-server-in-unreal-engine-4/

Categories: 

 

 

=================================

=================================

=================================

 

 

 

출처: http://cafe.naver.com/unrealenginekr/11101

 

 

만들어진 서버에 접속하는 

 

클라이언트를 만드려고 

https://wiki.unrealengine.com/TCP_Socket_Listener,_Receive_Binary_Data_From_an_IP/Port_Into_UE4,_(Full_Code_Sample)

예제를 보면서 해보고 있지만

빌드가 잘 안되네여..

 

저 ㅇㅖ제 해보신분들의 자세한 도움이 필요합니다~

어떤 클래스를 상속받아서 작성해야 하는지..

포함디렉터리가 있다면 무엇을 어디에 해야하는지..

어떤 헤더 들이 필요한지... ㅜ 

 

 

 

FSocket 써서 클라이언트 작업 하신분 샘플 소스좀 공유해주세요~~ ㅜㅜ

 

----------------------------------------------------------------------------------------------------------------------------------------------

 

dll 추가하셨나요

 

 

어떤dll을 어디에 해줘야하는지 다 모르겠습니다ㅜ

  정회원   
2016.08.18. 10:58

TCP를 사용하시겠다면 아래 코드를 참고 해 보세요.

https://wiki.unrealengine.com/TCP_Socket_Listener,_Receive_Binary_Data_From_an_IP/Port_Into_UE4,_(Full_Code_Sample)

 

UDP를 사용하시겠다면 아래 코드를 참조하시면 됩니다.

https://wiki.unrealengine.com/UDP_Socket_Sender_Receiver_From_One_UE4_Instance_To_Another

 

FUdpSocketReceiver의 경우 FRunnable을 상속받았기에, 알아서 데이터를 척척 받아줍니다.

다만 TCP로 구현하신다면, 루프를 돌리지 마시고 쓰레드로 구현하시는게 좋을 것 같습니다.

 

 

  • 답변 감사합니다!! 
    우선 저는 TCP로 다른 만들어져있는 서버에 IP/port로 접근하는 클라이언트를 만드려고 합니다.
    저 링크 저도 보고 따라서 해봤지만 빌드가 막혀서 헤더도 넣어보고 Actor에도 해봤다가 Pawn에도 해봤다가
    삽질 중입니다 ㅜㅜ 
    위 TCP링크의 코드를 어디에 코딩 해야 할지도 정확히 모르겠네요 ㅜㅜ
    클래스 만들떄 어떤 부모 클래스를 받아서 사용해야 할까요 ..? 
    혹시 다른 샘플 코드를 갖고 계신다면 공유 부탁드립니다 ㅜㅜ 
  •   ihopi
    2016.08.18. 11:30답글#include "Networking.h" 하나로 다 해결됩니다.
    언리얼에서 통신모듈을 상당히 간편하게 줄여두었습니다.
    그리고 클래스는 액터로 만들어 사용하시기 바랍니다.
    생성과 종료 코드를 넣기가 편하거든요.

    제 프로젝트 때문에 어차피 TCP 모듈도 작성을 해서 테스트 해야 하는데, 조만간 간단한 샘플을 하나 만들어서 올리도록 하겠습니다.
  • 신고
  •   송쩡이
    2016.08.18. 11:57답글ihopi 네 감사합니다!
    #include "Networking.h" 는 넣었고
    //Start the Listener! //thread this eventually
    GetWorldTimerManager().SetTimer(this,
    &AGameModeTCPGameMode::TCPConnectionListener, 0.01, true);
    에서 막혀있습니다.
    액터로 만들어서 해봐야겠습니다. 감사합니다!
  • 신고
  •   ihopi
    2016.08.18. 12:57답글송쩡이 그 부분은 타이머를 세팅하는건데요.
    컴파일 에러가 나는건가요?

    막혀있다는게 어떤건지 알려주시면 도움드릴 수 있을 듯 합니다.
  • 신고
  •   송쩡이
    2016.08.18. 14:37답글ihopi 네 컴파일 에러입니다.

    1>D:\3_Unrealpro\ActorTCP\Source\ActorTCP\Tcp_Actor.cpp(48): error C2664: 'void FTimerManager::SetTimer(FTimerHandle &,TFunction<void (void)> &&,float,bool,float)': 인수 1을(를) 'ATcp_Actor *const '에서 'FTimerHandle &'(으)로 변환할 수 없습니다.
    1>ERROR : UBT error : Failed to produce item: D:\3_Unrealpro\ActorTCP\Binaries\Win64\UE4Editor-ActorTCP-8164.dll

    AActor 상속받은 상태이구요
    cpp에서 식별자 GetWorldTimerManager() 가 정의 되어 있지 않습니다라고 나옵니다

    게임 모드에서 했을때는
    GetWorldTimerManager().SetTimer 에서 중간에 . 에 밑줄이있습니다. 

  • 신고
  •   송쩡이
    2016.08.18. 14:52답글카테고리 GetWorldTimerManager().SetTimer(this,
    &ATcp_Actor::TCPConnectionListener, 0.01, true);
    요렇게 되있습니다 ㅎㅎ 관심감사합니다
  • 신고
  •   카테고리
    2016.08.18. 15:22답글송쩡이 찾아보니 저 SetTimer() 함수의 파라메터가 바뀌었더군요.
    헤더에 FTimerHandle TimerHandleDelayedPlay; 이런식으로 타이머 핸들 하나 정의해 주시고.
    GetWorldTimerManager().SetTimer(TimerHandleDelayedPlay, this, &AActorLift::SetDelayedPlay, 3.f, false);
    이런식으로 첫 파라메터로 위 정의한 타이머핸들 넣어주시면... 아마도, 왠만하면... 되겠죠?;;
  • 신고
  •   송쩡이
    2016.08.18. 15:27답글카테고리 감사합니다~ ㅎㅎ 
    하지만 Actor에서는 애초에 GetWorldTimerManager() 가 정의 되어 있지 않다고 해서
    적용을 할 수 가 없습니다.. ㅎㅎ 왜 안뜨는걸까요 왜죠..
  • 신고
  •   송쩡이
    2016.08.18. 15:29답글카테고리 혹시
    저 예제에서 
    void AYourClass::Laaaaaauuuunch()
    {
    //IP = 127.0.0.1, Port = 8890 for my Python test case
    if( ! StartTCPReceiver("RamaSocketListener", "127.0.0.1", 8890))
    {
    //UE_LOG "TCP Socket Listener Created!"
    return;
    }

    //UE_LOG "TCP Socket Listener Created! Yay!"
    }

    이 함수는 어디에 쓰는건지 아시나요?? 완성된 코드긴 한가요??
    알아 차릴수 있다고하지만 저는 모르겠습니다.....
  • 신고
  •   카테고리
    2016.08.18. 15:39답글송쩡이 GetWorldTimerManager 는 엔진의 Actor.h에 기본으로 정의 되어있습니다.
    혹시 액터를 상속받지 않으신게 아닌지?
    그렇다면...
    GetWorld()->GetTimerManager().SetTimer(...)
    이런식으로 접근해 보세요.
  • 신고
  •   카테고리
    2016.08.18. 15:46답글Laaaaaauuuunch() 함수는 Tcp 서버의 리스너 소켓을 여는코드인데요... 
    주석에도 그렇게 적혀있고...
    무엇을 묻는건지 잘 이해가 안가네요.
  • 신고
  •   송쩡이
    2016.08.18. 16:21답글아 네네 ㅎㅎ 이해했습니다. 감사합니다
  • 신고

 

 

=================================

=================================

=================================

 

 

출처: https://wiki.unrealengine.com/UDP_Socket_Sender_Receiver_From_One_UE4_Instance_To_Another

 

 

UDP Socket Sender Receiver From One UE4 Instance To Another

Contents

 [hide

Overview

Author: Rama (talkwww.ue4code.com

In this tutorial I give you the core code for how you can send any custom data structure you want, BP-exposed, from one instance of UE4 to another!

The implications are vast, the use cases are nearly infinite!

You can send any data you want from any 1 UE4 instance to any other!

 

 

Setup

Below are two actor classes, you should spawn 1 in your sending instance of UE4 and 1 in your receiving instance of UE4, of the respective types.

The reason they are actors is to allow them to be easily blueprintable and have async BP event responses via BlueprintImplementable event.

I used this ip,port

IP = 127.0.0.1

Port = 8890

The IP is passed in an FString

Build CS

Make sure to include the extra dependencies!

PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore",   "Sockets", "Networking" //<~~~~~ });

Custom Data

The core of my method is that your data structure must have its own serialization function defined, here is the code for a BP exposed serializable data structure in UE4.

#pragma once
 
#include "AnyCustomData.generated.h"
 
USTRUCT(BlueprintType)
struct FAnyCustomData
{ 
	GENERATED_USTRUCT_BODY()
 
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Joy Color")
	FString Name = "Victory!";
 
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Joy Color")
	int32 Count = 1;
 
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Joy Color")
	float Scale = 1.f;
 
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Joy Color")
	FLinearColor Color = FLinearColor::Red;
 
	FAnyCustomData()
	{}
};
 
FORCEINLINE FArchive& operator<<(FArchive &Ar, FAnyCustomData& TheStruct )
{
	Ar << TheStruct.Name; 
	Ar << TheStruct.Count; 
	Ar << TheStruct.Scale; 
	Ar << TheStruct.Color;
 
	return Ar;
}

As you can see am using a C++ operator overload of operator<< to tell UE4's FArchive how to serialize my data structure.

Because the data types are simple I can rely on UE4's existing serialization overloads for each simple data type.

Sender

.h

/*
 
	By Rama
 
*/
#pragma once
 
//Networking
#include "Networking.h"
 
//Base
#include "RamaUDPSender.generated.h"
 
UCLASS()
class ARamaUDPSender : public AActor
{
	GENERATED_UCLASS_BODY()
 
	bool IsUDP;
 
	//UFUNCTION(BlueprintCallable, Category=RamaUDPSender)
	bool RamaUDPSender_SendString(FString ToSend);
 
public:
	TSharedPtr<FInternetAddr>	RemoteAddr;
	FSocket* SenderSocket;
 
	bool StartUDPSender(
		const FString& YourChosenSocketName,
		const FString& TheIP, 
		const int32 ThePort,
		bool UDP = false
	);
 
public:
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Rama UDP Sender")
	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::Printf(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::Printf(TEXT("%s %s"), *Msg, *Msg2));
	}
 
 
public:
 
	/** Called whenever this actor is being removed from a level */
	virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
};

.cpp

/*
 
	RamaUDPSender
 
	by Rama
*/
#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)
	{
		SenderSocket->Close();
		ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(SenderSocket);
	}
}
 
bool ARamaUDPSender::StartUDPSender(
	const FString& YourChosenSocketName,
	const FString& TheIP, 
	const int32 ThePort
){	
	//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()
	;
 
 
	//check(SenderSocket->GetSocketType() == SOCKTYPE_Datagram);
 
	//Set Send Buffer Size
	int32 SendSize = 2*1024*1024;
	SenderSocket->SetSendBufferSize(SendSize,SendSize);
	SenderSocket->SetReceiveBufferSize(SendSize, SendSize);
 
	UE_LOG(LogTemp,Log,TEXT("\n\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"));
	UE_LOG(LogTemp,Log,TEXT("Rama ****UDP**** Sender Initialized Successfully!!!"));
	UE_LOG(LogTemp,Log,TEXT("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n\n"));
 
	return true;
}
 
bool ARamaUDPSender::RamaUDPSender_SendString(FString ToSend)
{
	if(!SenderSocket) 
	{
		ScreenMsg("No sender socket");
		return false;
	}
	//~~~~~~~~~~~~~~~~
 
	int32 BytesSent = 0;
 
	FAnyCustomData NewData;
	NewData.Scale = FMath::FRandRange(0,1000);
	NewData.Count = FMath::RandRange(0,100);
	NewData.Color = FLinearColor(FMath::FRandRange(0,1),FMath::FRandRange(0,1),FMath::FRandRange(0,1),1);
 
	FArrayWriter Writer;
 
	Writer << NewData; //Serializing our custom data, thank you UE4!
 
	SenderSocket->SendTo(Writer.GetData(),Writer.Num(),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! Bytes Sent = ",BytesSent );
 
	return true;
}

The core here is:

FArrayWriter Writer;
 
Writer << NewData; //Serializing our custom data, thank you UE4!
 
SenderSocket->SendTo(Writer.GetData(),Writer.Num(),BytesSent,*RemoteAddr);

I am using UE4's ArrayWriter to do the serializtion and then send this serialized data over the network.

Receiver

.h

/*
 
	By Rama
 
*/
#pragma once
 
//Networking
#include "Networking.h"
 
//Base
#include "RamaUDPReceiver.generated.h"
 
UCLASS()
class ARamaUDPReceiver : public AActor
{
	GENERATED_UCLASS_BODY()
 
//====================================================
//		Data Received Events!
public:
	/** Data has been received!! */
	UFUNCTION(BlueprintImplementableEvent)
	void BPEvent_DataReceived(const FAnyCustomData& ReceivedData );
 
//====================================================
 
public:
	FSocket* ListenSocket;
 
	FUdpSocketReceiver* UDPReceiver = nullptr;
	void Recv(const FArrayReaderPtr& ArrayReaderPtr, const FIPv4Endpoint& EndPt);
 
	bool StartUDPReceiver(
		const FString& YourChosenSocketName,
		const FString& TheIP, 
		const int32 ThePort
	);
 
//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::Printf(TEXT("%s %f"), *Msg, Value));
	}
	FORCEINLINE void ScreenMsg(const FString& Msg, const FString& Msg2)
	{
		GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("%s %s"), *Msg, *Msg2));
	}
 
 
public:
 
	/** Called whenever this actor is being removed from a level */
	virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
};

.cpp

/*
 
	RamaUDPReceiver
 
	by Rama
*/
#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);
	}
}
 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
//Rama's Start TCP Receiver
bool ARamaUDPReceiver::StartUDPReceiver(
	const FString& YourChosenSocketName,
	const FString& TheIP, 
	const int32 ThePort
){
 
	ScreenMsg("RECEIVER INIT");
 
	//~~~
 
	FIPv4Address Addr;
	FIPv4Address::Parse(TheIP, Addr);
 
	//Create Socket
	FIPv4Endpoint Endpoint(Addr, ThePort);
 
	//BUFFER SIZE
	int32 BufferSize = 2*1024*1024;
 
	ListenSocket = FUdpSocketBuilder(*YourChosenSocketName)
		.AsNonBlocking()
		.AsReusable()
		.BoundToEndpoint(Endpoint)
		.WithReceiveBufferSize(BufferSize);
	;
 
	FTimespan ThreadWaitTime = FTimespan::FromMilliseconds(100);
	UDPReceiver = new FUdpSocketReceiver(ListenSocket, ThreadWaitTime, TEXT("UDP RECEIVER"));
	UDPReceiver->OnDataReceived().BindUObject(this, &ARamaUDPReceiver::Recv); 
 
	return true;
}
 
void ARamaUDPReceiver::Recv(const FArrayReaderPtr& ArrayReaderPtr, const FIPv4Endpoint& EndPt)
{
	ScreenMsg("Received bytes", ArrayReaderPtr->Num() );
 
	FAnyCustomData Data;
	*ArrayReaderPtr << Data;		//Now de-serializing! See AnyCustomData.h
 
	//BP Event
	BPEvent_DataReceived(Data);
}

The core here is the binding of the receiver thread delegate:

UDPReceiver->OnDataReceived().BindUObject(this, &ARamaUDPReceiver::Recv);

and then deserializing inside this delegate binded function:

FAnyCustomData Data;
*ArrayReaderPtr << Data;		//Now de-serializing! See AnyCustomData.h
 
//BP Event
BPEvent_DataReceived(Data);

 

TCP

I have a wiki on communicating via TCP here!TCP_Socket_Listener,_Receive_Binary_Data_From_an_IP/Port_Into_UE4,_(Full_Code_Sample)

Conclusion

As you can see I am using my custom USTRUCT serialization function to send any data I want from one instance of UE4 to another, and straight into Blueprints!

Now you can too!

Enjoy!

Rama (talkwww.ue4code.com

Category

 

=================================

=================================

=================================

 

 

출처: http://cafe.naver.com/unrealenginekr/9761

게임서버를 공부하고있는 학생입니다.

 

언리얼에서 c++ 클라로 게임을 만들어서

 

제가 제작한 임의의 서버를 연결한 네트워크 게임을 만들려고 하는데

검색해보면 전부 언리얼에서 제작해둔 서버를 사용하는거같더라구요..

 

따로 만든 IOCP나 TCP 서버와 연결하려고하면 


그냥 DirectX 나 C++ 클라이언트처럼 연동을 하면 되는건가요?

 

이부분이 확실하지 않아서.. 작업을 미뤄두고있는 상태라.. 

 

고수님들의 조언좀 부탁드립니다!!

 

---------------------------------------------------------------------------------------------------------------------------------------------------------------

 

(클라 측에서는)

언리얼에는  TCPLink 라는 클래스가 있습니다.  플랫폼에 무관하게 네트워킹 작업을 수행할 수 있게 Socket 를 wrapping 한 것으로 알고 있습니다.

 

일반적인 socket programming 에 대한 개념을 알고 있으면 쉽게 사용 가능할 것 같습니다.

 

(서버측에서는)

이전에  PC 온라인 게임 제작할 때와 같다고 생각하면 됩니다. 웹서버 방식으로 동작하는 게임 서버도 최근에는 많이 있긴한데, 이는 서버단에 로직을 구동하기가 쉽지 않습니다. 서버 로직을 구동하려면 자체 서버를 제작하는 것이 편할 겁니다.

 

최근 모바일 게임 서버도 일반적인 (이전과 같은) 온라인 게임 서버와 같은 방식으로 구동되고 있다고 생각하면 됩니다. 

 

 

2016.05.25. 00:24

네, 기존 C++ 라이브러리 연동하듯이 하시면 됩니다.

참고로, 프라우드넷의 C++ 라이브러리도 연동할 수 있습니다. 프라우드넷의 경우 Windows 뿐만 아니라 안드로이드,아이폰용 라이브러리도 같이 지원되므로, 멀티플랫폼 개발을 고려하시면 좋은 참고가 될겁니다.

 

언리얼엔진4에 프라우드넷 붙여 쓰는 방법 문서 링크 

 

  •   Ruthless
    2016.05.25. 00:40답글오오.. 넷텐션 대표님..
    혹시 프라우드넷을 적용한 UE4 샘플 프로젝트가 있을까요?

    정말 적용해보고 싶긴 한데 어느 단계부터 구현해야 될지 좀 막막해서요.
    https://docs.unrealengine.com/latest/KOR/Gameplay/Networking/Actors/index.html
    언리얼에서 기존에 지원하는 리플리케이션 기능을 사용하지 않고 프라우드넷에서 제공하는 것을 사용하여 만들어야 하는지도 궁금합니다.
  • 신고
  •   kalsbold
    2016.05.25. 18:13답글좋은정보 감사합니다 ㅎㅎ 하지만 제가 서버 전공중인 학생이라 제가 직접 만든 서버로 연동을 해야되서요 ㅎㅎ
  • 신고

 

 

=================================

=================================

=================================

 

 

관련링크들

 

https://forums.unrealengine.com/archive/index.php/t-18566.html

 

https://forums.unrealengine.com/archive/index.php/t-93419.html

 

https://forums.unrealengine.com/archive/index.php/t-62830.html

 

https://answers.unrealengine.com/questions/303656/error-on-socket-send.html

 

https://forums.unrealengine.com/showthread.php?22291-REQUEST-Tutorial-to-connect-to-dedicated-server-(Socket)

 

https://forums.unrealengine.com/showthread.php?18566-TCP-Socket-Listener-Receiving-Binary-Data-into-UE4-From-a-Python-Script!&highlight=tcp

 

https://forums.unrealengine.com/showthread.php?93419-Is-it-possible-to-create-Tcp-IP-Connection-using-Headers-from-Engine-Source-ThirdParty-Folder

 

 

https://gist.github.com/pnegri?direction=asc&sort=updated

 

http://vk.com/wall-68573701_90845

 

 

=================================

=================================

=================================

 

 

 

반응형
그리드형


관련글 더보기

댓글 영역