You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hi, would be nice as user point of view, to have the socket options already created, and also, let the user define if needed. So instead of him, know what is the option level, the option name, what is the value and so on ...
We could have something like:
With this, we could create as many options are there, and, with the benefit of templates compile time code generation, we could write just one setsockopt ...
classSocket
{
public:template <typename OPTION_TYPE>
structOption
{
Option(const std::int32_t level, const std::int32_t value)
: level(level), value(value), size(sizeof(OPTION_TYPE))
{
}
/** * The level argument*/const std::int32_t level;
/** * The optname argument )*/const std::int32_t value;
/** * The optlen argument*/const std::int32_t size;
/** * read from socket buffer size*/staticconst Option<std::int32_t> READ_BUFFER_SIZE_TYPE;
/** * When reading from socket, we define the timeout*/staticconst Option<structtimeval> READ_TIMEOUT;
/** * Minimum number of bytes to consider the buffer as readable * Can be useful if want to use batch messages*/staticconst Option<std::int32_t>
MINIMUM_BYTES_TO_CONSIDER_BUFFER_AS_READABLE;
/** * This option is used to enable the TCP Corking mechanism, * which delays sending small packets in order to optimize network * throughput.*/staticconst Option<std::int32_t> TCP_CORKING;
/** * Indicates that the rules used in validating addresses * supplied in a bind(2) call should allow reuse of local * addresses. For AF_INET sockets this means that a socket * may bind, except when there is an active listening socket * bound to the address. When the listening socket is bound * to INADDR_ANY with a specific port then it is not possible * to bind to this port for any local address.*/staticconst Option<std::int32_t> REUSE_ADDRESS;
/** * Permits multiple AF_INET or AF_INET6 sockets to be bound * to an identical socket address. This option must be set * on each socket (including the first socket) prior to * calling bind(2) on the socket. To prevent port hijacking, * all of the processes binding to the same address must have * the same effective UID. This option can be employed with * both TCP and UDP sockets.*/staticconst Option<std::int32_t> REUSE_PORT;
/* * If set, disable the Nagle algorithm. This means that * segments are always sent as soon as possible, even if * there is only a small amount of data. When not set, data * is buffered until there is a sufficient amount to send * out, thereby avoiding the frequent sending of small * packets, which results in poor utilization of the network. * https://en.wikipedia.org/wiki/Nagle%27s_algorithm its useful to undestand this ...*/staticconst Option<std::int32_t> TCP_NO_DELAY;
/** * If defined, tries to send al enqued messages before socket.close or * socket.shutdown return. So, if the send exceeds the timeout defined * in the linger option*/staticconst Option<structlinger> LINGER;
};
template <typename VALUE_TYPE>
structOptionValue
{
OptionValue(const VALUE_TYPE value_type, const Option<VALUE_TYPE>& type) : value_type(value_type), type(type)
{}
/** * Since the options are static instances, we can use lvalue here*/const Option<VALUE_TYPE>& type;
const VALUE_TYPE value_type;
};
template <typename TYPE>
voidset_option(const OptionValue<TYPE> option) const
{
int32_t level = option.type.level;
int32_t opt_name = option.type.value;
TYPE t = option.value_type;
void* opt_value = &(t);
socklen_t opt_len = option.type.size;
if (::setsockopt(file_descriptor, level, opt_name, opt_value, opt_len) == -1)
{
perror("setsockopt");
}
};
template <typename TYPE>
const OptionValue<TYPE> get_option(const Option<TYPE>& type) const
{
int32_t socketfd = file_descriptor;
int32_t level = type.level;
int32_t opt_name = type.value;
/** * NOTE: This is not a Variable Length Array. * We can achive this, with templates, so its know at compile time how * big it is.*/
std::int8_t buffer[type.size];
socklen_t opt_len;
if (::getsockopt(socketfd, level, opt_name, buffer, &opt_len) == -1)
{
perror("getsockopt");
}
TYPE* t = reinterpret_cast<TYPE*>(buffer);
const OptionValue<TYPE> result(*t, type);
return result;
}
}
template <>
Socket::Option<int32_t> const Socket::Option<int32_t>::TCP_CORKING;
template <>
Socket::Option<int32_t> const Socket::Option<int32_t>::MINIMUM_BYTES_TO_CONSIDER_BUFFER_AS_READABLE;
template <>
Socket::Option<int32_t> const Socket::Option<int32_t>::READ_BUFFER_SIZE_TYPE;
template <>
Socket::Option<structtimeval> const Socket::Option<structtimeval>::READ_TIMEOUT;
template <>
Socket::Option<std::int32_t> const Socket::Option<std::int32_t>::REUSE_ADDRESS;
template <>
Socket::Option<std::int32_t> const Socket::Option<std::int32_t>::REUSE_PORT;
template <>
Socket::Option<std::int32_t> const Socket::Option<std::int32_t>::TCP_NO_DELAY;
template <>
Socket::Option<structlinger> const Socket::Option<structlinger>::LINGER;
Description
Hi, would be nice as user point of view, to have the socket options already created, and also, let the user define if needed. So instead of him, know what is the option level, the option name, what is the value and so on ...
We could have something like:
With this, we could create as many options are there, and, with the benefit of templates compile time code generation, we could write just one setsockopt ...
I was seeing Socket.h, and noticied:
This works fine, but leads to duplicated code ...
Example
A more detailed example: Socket.h
And, Socket.cc
Note: The code of set_option and get_option must be in the header file, because we are using templates.
Note sure if there is a more elegant way ...
And, the usage:
If you liked, and accept. I would like to implement it!
Thanks!
The text was updated successfully, but these errors were encountered: