C++ game server












1















I'm writing a server for an MMO game using boost::asio. I would like to know, are there any design or other issues in my code? And what should I improve in it? Thanks in advance.



BaseServer.h:



#ifndef BASE_SERVER_H
#define BASE_SERVER_H

#include <asio.hpp>
#include "MessageProcessor.h"

class BaseServer
{
public:
BaseServer(asio::io_context& ioContext, unsigned short port)
: socket(ioContext, asio::ip::udp::endpoint(asio::ip::udp::v4(), port))
{
receivePacket();
}

protected:
asio::ip::udp::socket socket;

virtual void handlePacket() = 0;

private:
void receivePacket()
{
socket.async_receive(asio::null_buffers(), [this](std::error_code ec, std::size_t bytes_recvd)
{
if (ec == asio::error::operation_aborted) return;
handlePacket();
receivePacket();
});
}
};

#endif


GameServer.h:



#ifndef GAME_SERVER_H
#define GAME_SERVER_H

#include <Net/BaseServer.h>
#include <Net/MessageProcessor.h>
#include <Utils/BitStream.h>

class GameServer : public BaseServer
{
public:
GameServer(asio::io_context& ioContext, unsigned short port);

protected:
MessageProcessor<BitStream&, asio::ip::udp::endpoint> messageProcessor;

void asyncParsePacket(unsigned char* buffer, unsigned short packetSize, asio::ip::udp::endpoint senderEndpoint);
virtual void handlePacket() override;
};

#endif


GameServer.cpp:



#include "GameServer.h"

#include <iostream>
#include "Messages/Client/TestMessage.h"

GameServer::GameServer(asio::io_context& ioContext, unsigned short port)
: BaseServer(ioContext, port)
{
messageProcessor.registerHandler(0x01, (BitStream& stream, asio::ip::udp::endpoint endpoint)
{
TestMessage mes;
mes.deserialize(stream);

std::cout << "Test message received! A = " << mes.a << ", B = " << mes.b << std::endl;
});
}

void GameServer::asyncParsePacket(unsigned char* buffer, unsigned short packetSize, asio::ip::udp::endpoint senderEndpoint)
{
BitStream stream(buffer, packetSize);
delete buffer;
unsigned char messageId;
stream >> messageId;

auto handler = messageProcessor.getHandler(messageId);
if (handler) handler(stream, senderEndpoint);
}

void GameServer::handlePacket()
{
unsigned int available = socket.available();
unsigned char* buffer = new unsigned char[available];
asio::ip::udp::endpoint senderEndpoint;
std::error_code ec;
unsigned short packetSize = socket.receive_from(asio::buffer(buffer, available), senderEndpoint, 0, ec);
socket.get_io_service().post(std::bind(&AuthServer::asyncParsePacket, this, buffer, packetSize, senderEndpoint));
}


BaseMessage.h:



#ifndef BASE_MESSAGE_H
#define BASE_MESSAGE_H

#include "../Utils/BitStream.h"

class BaseMessage
{
protected:
unsigned short id;

public:
BaseMessage(unsigned short messageId)
: id(messageId) {}
virtual ~BaseMessage() = default;

unsigned short getId() const { return this->id; }

virtual void serialize(BitStream& stream) const = 0;
virtual void deserialize(BitStream& stream) = 0;
};

#endif


MessageProcessor.h



#ifndef MESSAGE_PROCESSOR_H
#define MESSAGE_PROCESSOR_H

#include <vector>
#include <functional>

class BitStream;

template <typename ... HandlerArgs>
class MessageProcessor
{
protected:
using MessageHandler = std::function<void (HandlerArgs ...)>;
std::vector<MessageHandler> messageHandlers;

public:
void registerHandler(unsigned short id, MessageHandler handler)
{
if (messageHandlers.size() <= id) messageHandlers.resize(id);
messageHandlers.insert(messageHandlers.begin() + id, handler);
}

MessageHandler getHandler(unsigned short id) const
{
return id < messageHandlers.size() ? messageHandlers[id] : 0;
}
};

#endif









share|improve this question









New contributor




Alex Kuzub is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





















  • Can you tell us more about the current functionality and why you're doing what you're doing? For example, what's the purpose of handlePacket() and why is receivePacket() called recursively?

    – Mast
    13 hours ago











  • @Mast receivePacket() is needed to encapsulate async_read function and avoid boilerplate code in derived classes. handlePacket() is like an onMessageReceived() callback. receivePacket() is called recursively because I need the server to receive messages in a loop.

    – Alex Kuzub
    13 hours ago













  • Are you aware there's such a thing as recursion depth and exceeding the maximum depth will result in a stack overflow? What is your maximum stack size and how long have you tried running your server? It should crash eventually if I read this right.

    – Mast
    13 hours ago











  • @Mast This is not a recursion. async_receive is an asynchronous function, so it just adds new async request to the I/O queue and exits immediately.

    – Alex Kuzub
    13 hours ago
















1















I'm writing a server for an MMO game using boost::asio. I would like to know, are there any design or other issues in my code? And what should I improve in it? Thanks in advance.



BaseServer.h:



#ifndef BASE_SERVER_H
#define BASE_SERVER_H

#include <asio.hpp>
#include "MessageProcessor.h"

class BaseServer
{
public:
BaseServer(asio::io_context& ioContext, unsigned short port)
: socket(ioContext, asio::ip::udp::endpoint(asio::ip::udp::v4(), port))
{
receivePacket();
}

protected:
asio::ip::udp::socket socket;

virtual void handlePacket() = 0;

private:
void receivePacket()
{
socket.async_receive(asio::null_buffers(), [this](std::error_code ec, std::size_t bytes_recvd)
{
if (ec == asio::error::operation_aborted) return;
handlePacket();
receivePacket();
});
}
};

#endif


GameServer.h:



#ifndef GAME_SERVER_H
#define GAME_SERVER_H

#include <Net/BaseServer.h>
#include <Net/MessageProcessor.h>
#include <Utils/BitStream.h>

class GameServer : public BaseServer
{
public:
GameServer(asio::io_context& ioContext, unsigned short port);

protected:
MessageProcessor<BitStream&, asio::ip::udp::endpoint> messageProcessor;

void asyncParsePacket(unsigned char* buffer, unsigned short packetSize, asio::ip::udp::endpoint senderEndpoint);
virtual void handlePacket() override;
};

#endif


GameServer.cpp:



#include "GameServer.h"

#include <iostream>
#include "Messages/Client/TestMessage.h"

GameServer::GameServer(asio::io_context& ioContext, unsigned short port)
: BaseServer(ioContext, port)
{
messageProcessor.registerHandler(0x01, (BitStream& stream, asio::ip::udp::endpoint endpoint)
{
TestMessage mes;
mes.deserialize(stream);

std::cout << "Test message received! A = " << mes.a << ", B = " << mes.b << std::endl;
});
}

void GameServer::asyncParsePacket(unsigned char* buffer, unsigned short packetSize, asio::ip::udp::endpoint senderEndpoint)
{
BitStream stream(buffer, packetSize);
delete buffer;
unsigned char messageId;
stream >> messageId;

auto handler = messageProcessor.getHandler(messageId);
if (handler) handler(stream, senderEndpoint);
}

void GameServer::handlePacket()
{
unsigned int available = socket.available();
unsigned char* buffer = new unsigned char[available];
asio::ip::udp::endpoint senderEndpoint;
std::error_code ec;
unsigned short packetSize = socket.receive_from(asio::buffer(buffer, available), senderEndpoint, 0, ec);
socket.get_io_service().post(std::bind(&AuthServer::asyncParsePacket, this, buffer, packetSize, senderEndpoint));
}


BaseMessage.h:



#ifndef BASE_MESSAGE_H
#define BASE_MESSAGE_H

#include "../Utils/BitStream.h"

class BaseMessage
{
protected:
unsigned short id;

public:
BaseMessage(unsigned short messageId)
: id(messageId) {}
virtual ~BaseMessage() = default;

unsigned short getId() const { return this->id; }

virtual void serialize(BitStream& stream) const = 0;
virtual void deserialize(BitStream& stream) = 0;
};

#endif


MessageProcessor.h



#ifndef MESSAGE_PROCESSOR_H
#define MESSAGE_PROCESSOR_H

#include <vector>
#include <functional>

class BitStream;

template <typename ... HandlerArgs>
class MessageProcessor
{
protected:
using MessageHandler = std::function<void (HandlerArgs ...)>;
std::vector<MessageHandler> messageHandlers;

public:
void registerHandler(unsigned short id, MessageHandler handler)
{
if (messageHandlers.size() <= id) messageHandlers.resize(id);
messageHandlers.insert(messageHandlers.begin() + id, handler);
}

MessageHandler getHandler(unsigned short id) const
{
return id < messageHandlers.size() ? messageHandlers[id] : 0;
}
};

#endif









share|improve this question









New contributor




Alex Kuzub is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





















  • Can you tell us more about the current functionality and why you're doing what you're doing? For example, what's the purpose of handlePacket() and why is receivePacket() called recursively?

    – Mast
    13 hours ago











  • @Mast receivePacket() is needed to encapsulate async_read function and avoid boilerplate code in derived classes. handlePacket() is like an onMessageReceived() callback. receivePacket() is called recursively because I need the server to receive messages in a loop.

    – Alex Kuzub
    13 hours ago













  • Are you aware there's such a thing as recursion depth and exceeding the maximum depth will result in a stack overflow? What is your maximum stack size and how long have you tried running your server? It should crash eventually if I read this right.

    – Mast
    13 hours ago











  • @Mast This is not a recursion. async_receive is an asynchronous function, so it just adds new async request to the I/O queue and exits immediately.

    – Alex Kuzub
    13 hours ago














1












1








1


0






I'm writing a server for an MMO game using boost::asio. I would like to know, are there any design or other issues in my code? And what should I improve in it? Thanks in advance.



BaseServer.h:



#ifndef BASE_SERVER_H
#define BASE_SERVER_H

#include <asio.hpp>
#include "MessageProcessor.h"

class BaseServer
{
public:
BaseServer(asio::io_context& ioContext, unsigned short port)
: socket(ioContext, asio::ip::udp::endpoint(asio::ip::udp::v4(), port))
{
receivePacket();
}

protected:
asio::ip::udp::socket socket;

virtual void handlePacket() = 0;

private:
void receivePacket()
{
socket.async_receive(asio::null_buffers(), [this](std::error_code ec, std::size_t bytes_recvd)
{
if (ec == asio::error::operation_aborted) return;
handlePacket();
receivePacket();
});
}
};

#endif


GameServer.h:



#ifndef GAME_SERVER_H
#define GAME_SERVER_H

#include <Net/BaseServer.h>
#include <Net/MessageProcessor.h>
#include <Utils/BitStream.h>

class GameServer : public BaseServer
{
public:
GameServer(asio::io_context& ioContext, unsigned short port);

protected:
MessageProcessor<BitStream&, asio::ip::udp::endpoint> messageProcessor;

void asyncParsePacket(unsigned char* buffer, unsigned short packetSize, asio::ip::udp::endpoint senderEndpoint);
virtual void handlePacket() override;
};

#endif


GameServer.cpp:



#include "GameServer.h"

#include <iostream>
#include "Messages/Client/TestMessage.h"

GameServer::GameServer(asio::io_context& ioContext, unsigned short port)
: BaseServer(ioContext, port)
{
messageProcessor.registerHandler(0x01, (BitStream& stream, asio::ip::udp::endpoint endpoint)
{
TestMessage mes;
mes.deserialize(stream);

std::cout << "Test message received! A = " << mes.a << ", B = " << mes.b << std::endl;
});
}

void GameServer::asyncParsePacket(unsigned char* buffer, unsigned short packetSize, asio::ip::udp::endpoint senderEndpoint)
{
BitStream stream(buffer, packetSize);
delete buffer;
unsigned char messageId;
stream >> messageId;

auto handler = messageProcessor.getHandler(messageId);
if (handler) handler(stream, senderEndpoint);
}

void GameServer::handlePacket()
{
unsigned int available = socket.available();
unsigned char* buffer = new unsigned char[available];
asio::ip::udp::endpoint senderEndpoint;
std::error_code ec;
unsigned short packetSize = socket.receive_from(asio::buffer(buffer, available), senderEndpoint, 0, ec);
socket.get_io_service().post(std::bind(&AuthServer::asyncParsePacket, this, buffer, packetSize, senderEndpoint));
}


BaseMessage.h:



#ifndef BASE_MESSAGE_H
#define BASE_MESSAGE_H

#include "../Utils/BitStream.h"

class BaseMessage
{
protected:
unsigned short id;

public:
BaseMessage(unsigned short messageId)
: id(messageId) {}
virtual ~BaseMessage() = default;

unsigned short getId() const { return this->id; }

virtual void serialize(BitStream& stream) const = 0;
virtual void deserialize(BitStream& stream) = 0;
};

#endif


MessageProcessor.h



#ifndef MESSAGE_PROCESSOR_H
#define MESSAGE_PROCESSOR_H

#include <vector>
#include <functional>

class BitStream;

template <typename ... HandlerArgs>
class MessageProcessor
{
protected:
using MessageHandler = std::function<void (HandlerArgs ...)>;
std::vector<MessageHandler> messageHandlers;

public:
void registerHandler(unsigned short id, MessageHandler handler)
{
if (messageHandlers.size() <= id) messageHandlers.resize(id);
messageHandlers.insert(messageHandlers.begin() + id, handler);
}

MessageHandler getHandler(unsigned short id) const
{
return id < messageHandlers.size() ? messageHandlers[id] : 0;
}
};

#endif









share|improve this question









New contributor




Alex Kuzub is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.












I'm writing a server for an MMO game using boost::asio. I would like to know, are there any design or other issues in my code? And what should I improve in it? Thanks in advance.



BaseServer.h:



#ifndef BASE_SERVER_H
#define BASE_SERVER_H

#include <asio.hpp>
#include "MessageProcessor.h"

class BaseServer
{
public:
BaseServer(asio::io_context& ioContext, unsigned short port)
: socket(ioContext, asio::ip::udp::endpoint(asio::ip::udp::v4(), port))
{
receivePacket();
}

protected:
asio::ip::udp::socket socket;

virtual void handlePacket() = 0;

private:
void receivePacket()
{
socket.async_receive(asio::null_buffers(), [this](std::error_code ec, std::size_t bytes_recvd)
{
if (ec == asio::error::operation_aborted) return;
handlePacket();
receivePacket();
});
}
};

#endif


GameServer.h:



#ifndef GAME_SERVER_H
#define GAME_SERVER_H

#include <Net/BaseServer.h>
#include <Net/MessageProcessor.h>
#include <Utils/BitStream.h>

class GameServer : public BaseServer
{
public:
GameServer(asio::io_context& ioContext, unsigned short port);

protected:
MessageProcessor<BitStream&, asio::ip::udp::endpoint> messageProcessor;

void asyncParsePacket(unsigned char* buffer, unsigned short packetSize, asio::ip::udp::endpoint senderEndpoint);
virtual void handlePacket() override;
};

#endif


GameServer.cpp:



#include "GameServer.h"

#include <iostream>
#include "Messages/Client/TestMessage.h"

GameServer::GameServer(asio::io_context& ioContext, unsigned short port)
: BaseServer(ioContext, port)
{
messageProcessor.registerHandler(0x01, (BitStream& stream, asio::ip::udp::endpoint endpoint)
{
TestMessage mes;
mes.deserialize(stream);

std::cout << "Test message received! A = " << mes.a << ", B = " << mes.b << std::endl;
});
}

void GameServer::asyncParsePacket(unsigned char* buffer, unsigned short packetSize, asio::ip::udp::endpoint senderEndpoint)
{
BitStream stream(buffer, packetSize);
delete buffer;
unsigned char messageId;
stream >> messageId;

auto handler = messageProcessor.getHandler(messageId);
if (handler) handler(stream, senderEndpoint);
}

void GameServer::handlePacket()
{
unsigned int available = socket.available();
unsigned char* buffer = new unsigned char[available];
asio::ip::udp::endpoint senderEndpoint;
std::error_code ec;
unsigned short packetSize = socket.receive_from(asio::buffer(buffer, available), senderEndpoint, 0, ec);
socket.get_io_service().post(std::bind(&AuthServer::asyncParsePacket, this, buffer, packetSize, senderEndpoint));
}


BaseMessage.h:



#ifndef BASE_MESSAGE_H
#define BASE_MESSAGE_H

#include "../Utils/BitStream.h"

class BaseMessage
{
protected:
unsigned short id;

public:
BaseMessage(unsigned short messageId)
: id(messageId) {}
virtual ~BaseMessage() = default;

unsigned short getId() const { return this->id; }

virtual void serialize(BitStream& stream) const = 0;
virtual void deserialize(BitStream& stream) = 0;
};

#endif


MessageProcessor.h



#ifndef MESSAGE_PROCESSOR_H
#define MESSAGE_PROCESSOR_H

#include <vector>
#include <functional>

class BitStream;

template <typename ... HandlerArgs>
class MessageProcessor
{
protected:
using MessageHandler = std::function<void (HandlerArgs ...)>;
std::vector<MessageHandler> messageHandlers;

public:
void registerHandler(unsigned short id, MessageHandler handler)
{
if (messageHandlers.size() <= id) messageHandlers.resize(id);
messageHandlers.insert(messageHandlers.begin() + id, handler);
}

MessageHandler getHandler(unsigned short id) const
{
return id < messageHandlers.size() ? messageHandlers[id] : 0;
}
};

#endif






c++ game networking server boost






share|improve this question









New contributor




Alex Kuzub is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











share|improve this question









New contributor




Alex Kuzub is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this question




share|improve this question








edited 13 hours ago









Edward

46.5k378210




46.5k378210






New contributor




Alex Kuzub is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked 13 hours ago









Alex KuzubAlex Kuzub

82




82




New contributor




Alex Kuzub is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





Alex Kuzub is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






Alex Kuzub is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.













  • Can you tell us more about the current functionality and why you're doing what you're doing? For example, what's the purpose of handlePacket() and why is receivePacket() called recursively?

    – Mast
    13 hours ago











  • @Mast receivePacket() is needed to encapsulate async_read function and avoid boilerplate code in derived classes. handlePacket() is like an onMessageReceived() callback. receivePacket() is called recursively because I need the server to receive messages in a loop.

    – Alex Kuzub
    13 hours ago













  • Are you aware there's such a thing as recursion depth and exceeding the maximum depth will result in a stack overflow? What is your maximum stack size and how long have you tried running your server? It should crash eventually if I read this right.

    – Mast
    13 hours ago











  • @Mast This is not a recursion. async_receive is an asynchronous function, so it just adds new async request to the I/O queue and exits immediately.

    – Alex Kuzub
    13 hours ago



















  • Can you tell us more about the current functionality and why you're doing what you're doing? For example, what's the purpose of handlePacket() and why is receivePacket() called recursively?

    – Mast
    13 hours ago











  • @Mast receivePacket() is needed to encapsulate async_read function and avoid boilerplate code in derived classes. handlePacket() is like an onMessageReceived() callback. receivePacket() is called recursively because I need the server to receive messages in a loop.

    – Alex Kuzub
    13 hours ago













  • Are you aware there's such a thing as recursion depth and exceeding the maximum depth will result in a stack overflow? What is your maximum stack size and how long have you tried running your server? It should crash eventually if I read this right.

    – Mast
    13 hours ago











  • @Mast This is not a recursion. async_receive is an asynchronous function, so it just adds new async request to the I/O queue and exits immediately.

    – Alex Kuzub
    13 hours ago

















Can you tell us more about the current functionality and why you're doing what you're doing? For example, what's the purpose of handlePacket() and why is receivePacket() called recursively?

– Mast
13 hours ago





Can you tell us more about the current functionality and why you're doing what you're doing? For example, what's the purpose of handlePacket() and why is receivePacket() called recursively?

– Mast
13 hours ago













@Mast receivePacket() is needed to encapsulate async_read function and avoid boilerplate code in derived classes. handlePacket() is like an onMessageReceived() callback. receivePacket() is called recursively because I need the server to receive messages in a loop.

– Alex Kuzub
13 hours ago







@Mast receivePacket() is needed to encapsulate async_read function and avoid boilerplate code in derived classes. handlePacket() is like an onMessageReceived() callback. receivePacket() is called recursively because I need the server to receive messages in a loop.

– Alex Kuzub
13 hours ago















Are you aware there's such a thing as recursion depth and exceeding the maximum depth will result in a stack overflow? What is your maximum stack size and how long have you tried running your server? It should crash eventually if I read this right.

– Mast
13 hours ago





Are you aware there's such a thing as recursion depth and exceeding the maximum depth will result in a stack overflow? What is your maximum stack size and how long have you tried running your server? It should crash eventually if I read this right.

– Mast
13 hours ago













@Mast This is not a recursion. async_receive is an asynchronous function, so it just adds new async request to the I/O queue and exits immediately.

– Alex Kuzub
13 hours ago





@Mast This is not a recursion. async_receive is an asynchronous function, so it just adds new async request to the I/O queue and exits immediately.

– Alex Kuzub
13 hours ago










1 Answer
1






active

oldest

votes


















1














You can make the call to recieve_from async by creating a temp struct with the variables you need to keep alive and the buffer. Then you can put it in a shared_ptr (to account for the potential copies and capture that shared_ptr in the lambda:



void GameServer::handlePacket()
{
unsigned int available = socket.available();
struct rec_data{
std::vector<unsigned char> buffer;
asio::ip::udp::endpoint senderEndpoint;
}

std::shared_ptr<rec_data> data = std::make_shared<rec_data>();
data->buffer.resize(available);

socket.receive_from(asio::buffer(data ->buffer.data(), available),
data ->senderEndpoint, 0,
[data](const std::error_code& error,
std::size_t bytes_transferred)
{
if(!error)
asyncParsePacket(data->buffer.data(), bytes_transferred, data->senderEndpoint);
});
}


The int you use for registerHandler is a magic number. Make it an enum and give each message type a name. Make sure to share the header between the sender and receiver.






share|improve this answer
























  • Thanks for your feedback.

    – Alex Kuzub
    12 hours ago











Your Answer





StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");

StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});






Alex Kuzub is a new contributor. Be nice, and check out our Code of Conduct.










draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f211330%2fc-game-server%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









1














You can make the call to recieve_from async by creating a temp struct with the variables you need to keep alive and the buffer. Then you can put it in a shared_ptr (to account for the potential copies and capture that shared_ptr in the lambda:



void GameServer::handlePacket()
{
unsigned int available = socket.available();
struct rec_data{
std::vector<unsigned char> buffer;
asio::ip::udp::endpoint senderEndpoint;
}

std::shared_ptr<rec_data> data = std::make_shared<rec_data>();
data->buffer.resize(available);

socket.receive_from(asio::buffer(data ->buffer.data(), available),
data ->senderEndpoint, 0,
[data](const std::error_code& error,
std::size_t bytes_transferred)
{
if(!error)
asyncParsePacket(data->buffer.data(), bytes_transferred, data->senderEndpoint);
});
}


The int you use for registerHandler is a magic number. Make it an enum and give each message type a name. Make sure to share the header between the sender and receiver.






share|improve this answer
























  • Thanks for your feedback.

    – Alex Kuzub
    12 hours ago
















1














You can make the call to recieve_from async by creating a temp struct with the variables you need to keep alive and the buffer. Then you can put it in a shared_ptr (to account for the potential copies and capture that shared_ptr in the lambda:



void GameServer::handlePacket()
{
unsigned int available = socket.available();
struct rec_data{
std::vector<unsigned char> buffer;
asio::ip::udp::endpoint senderEndpoint;
}

std::shared_ptr<rec_data> data = std::make_shared<rec_data>();
data->buffer.resize(available);

socket.receive_from(asio::buffer(data ->buffer.data(), available),
data ->senderEndpoint, 0,
[data](const std::error_code& error,
std::size_t bytes_transferred)
{
if(!error)
asyncParsePacket(data->buffer.data(), bytes_transferred, data->senderEndpoint);
});
}


The int you use for registerHandler is a magic number. Make it an enum and give each message type a name. Make sure to share the header between the sender and receiver.






share|improve this answer
























  • Thanks for your feedback.

    – Alex Kuzub
    12 hours ago














1












1








1







You can make the call to recieve_from async by creating a temp struct with the variables you need to keep alive and the buffer. Then you can put it in a shared_ptr (to account for the potential copies and capture that shared_ptr in the lambda:



void GameServer::handlePacket()
{
unsigned int available = socket.available();
struct rec_data{
std::vector<unsigned char> buffer;
asio::ip::udp::endpoint senderEndpoint;
}

std::shared_ptr<rec_data> data = std::make_shared<rec_data>();
data->buffer.resize(available);

socket.receive_from(asio::buffer(data ->buffer.data(), available),
data ->senderEndpoint, 0,
[data](const std::error_code& error,
std::size_t bytes_transferred)
{
if(!error)
asyncParsePacket(data->buffer.data(), bytes_transferred, data->senderEndpoint);
});
}


The int you use for registerHandler is a magic number. Make it an enum and give each message type a name. Make sure to share the header between the sender and receiver.






share|improve this answer













You can make the call to recieve_from async by creating a temp struct with the variables you need to keep alive and the buffer. Then you can put it in a shared_ptr (to account for the potential copies and capture that shared_ptr in the lambda:



void GameServer::handlePacket()
{
unsigned int available = socket.available();
struct rec_data{
std::vector<unsigned char> buffer;
asio::ip::udp::endpoint senderEndpoint;
}

std::shared_ptr<rec_data> data = std::make_shared<rec_data>();
data->buffer.resize(available);

socket.receive_from(asio::buffer(data ->buffer.data(), available),
data ->senderEndpoint, 0,
[data](const std::error_code& error,
std::size_t bytes_transferred)
{
if(!error)
asyncParsePacket(data->buffer.data(), bytes_transferred, data->senderEndpoint);
});
}


The int you use for registerHandler is a magic number. Make it an enum and give each message type a name. Make sure to share the header between the sender and receiver.







share|improve this answer












share|improve this answer



share|improve this answer










answered 12 hours ago









ratchet freakratchet freak

11.7k1341




11.7k1341













  • Thanks for your feedback.

    – Alex Kuzub
    12 hours ago



















  • Thanks for your feedback.

    – Alex Kuzub
    12 hours ago

















Thanks for your feedback.

– Alex Kuzub
12 hours ago





Thanks for your feedback.

– Alex Kuzub
12 hours ago










Alex Kuzub is a new contributor. Be nice, and check out our Code of Conduct.










draft saved

draft discarded


















Alex Kuzub is a new contributor. Be nice, and check out our Code of Conduct.













Alex Kuzub is a new contributor. Be nice, and check out our Code of Conduct.












Alex Kuzub is a new contributor. Be nice, and check out our Code of Conduct.
















Thanks for contributing an answer to Code Review Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


Use MathJax to format equations. MathJax reference.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f211330%2fc-game-server%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

How to reconfigure Docker Trusted Registry 2.x.x to use CEPH FS mount instead of NFS and other traditional...

is 'sed' thread safe

How to make a Squid Proxy server?