C++ game server
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
New contributor
add a comment |
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
New contributor
Can you tell us more about the current functionality and why you're doing what you're doing? For example, what's the purpose ofhandlePacket()
and why isreceivePacket()
called recursively?
– Mast
13 hours ago
@MastreceivePacket()
is needed to encapsulateasync_read
function and avoid boilerplate code in derived classes.handlePacket()
is like anonMessageReceived()
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
add a comment |
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
New contributor
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
c++ game networking server boost
New contributor
New contributor
edited 13 hours ago
Edward
46.5k378210
46.5k378210
New contributor
asked 13 hours ago
Alex KuzubAlex Kuzub
82
82
New contributor
New contributor
Can you tell us more about the current functionality and why you're doing what you're doing? For example, what's the purpose ofhandlePacket()
and why isreceivePacket()
called recursively?
– Mast
13 hours ago
@MastreceivePacket()
is needed to encapsulateasync_read
function and avoid boilerplate code in derived classes.handlePacket()
is like anonMessageReceived()
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
add a comment |
Can you tell us more about the current functionality and why you're doing what you're doing? For example, what's the purpose ofhandlePacket()
and why isreceivePacket()
called recursively?
– Mast
13 hours ago
@MastreceivePacket()
is needed to encapsulateasync_read
function and avoid boilerplate code in derived classes.handlePacket()
is like anonMessageReceived()
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
add a comment |
1 Answer
1
active
oldest
votes
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.
Thanks for your feedback.
– Alex Kuzub
12 hours ago
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
Thanks for your feedback.
– Alex Kuzub
12 hours ago
add a comment |
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.
Thanks for your feedback.
– Alex Kuzub
12 hours ago
add a comment |
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.
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.
answered 12 hours ago
ratchet freakratchet freak
11.7k1341
11.7k1341
Thanks for your feedback.
– Alex Kuzub
12 hours ago
add a comment |
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
add a comment |
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.
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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 isreceivePacket()
called recursively?– Mast
13 hours ago
@Mast
receivePacket()
is needed to encapsulateasync_read
function and avoid boilerplate code in derived classes.handlePacket()
is like anonMessageReceived()
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