MinimalSocket vous offre une bibliothèque C++ moderne pour configurer et créer des connexions socket TCP et UDP , d'une manière totalement indépendante de la plate-forme. Les systèmes pris en charge sont : Windows , toute distribution Linux et MacOS .
La section Fonctionnalités détaille les différentes fonctionnalités de MinimalSocket . Lisez Utilisation et exemples pour voir à quel point il est facile d'utiliser MinimalSocket .
Il s'agit d'un projet CMake , vérifiez le support CMake pour voir comment cette bibliothèque peut être intégrée.
N'oubliez pas de laisser une étoile au cas où vous auriez trouvé cette bibliothèque utile.
Vous n'avez pas déjà quitté une étoile ? Faites-le maintenant ;) !
MinimalSocket vous permet de créer et de configurer des connexions TCP et UDP . Les messages peuvent être envoyés et reçus en termes de tampon d'octets ou de chaînes. En effet, c'est en fait la seule fonctionnalité dont vous avez besoin pour un socket, car des messages plus complexes peuvent être sérialisés ou internalisés à partir d'un tampon d'octets en utilisant, entre autres, des approches telles que Google Protocol Buffers ou NanoPb.
Voici les caractéristiques les plus notables de MinimalSocket :
Ce tableau résume les différences entre les comportements bloquants et non bloquants du socket qui peuvent être créés à l'aide de MinimalSocket :
Comportement de blocage, l'appelant est bloqué jusqu'à la fin ou jusqu'à ce que le délai d'attente soit atteint (si un a été spécifié) | Comportement non bloquant, les fonctions reviennent immédiatement | |
---|---|---|
acceptation d'un nouveau client (tcp uniquement) | le thread appelant est absorbé jusqu'à ce qu'un nouveau client demande réellement à se connecter ou que le délai d'attente soit atteint (le cas échéant) | si une demande de connexion d'un client était déjà mise en file d'attente avant d'appeler la fonction accept, un nouveau gestionnaire de connexion est renvoyé, sinon un nullopt est renvoyé. |
recevoir un nouveau message (tcp et udp) | le thread appelant est absorbé jusqu'à ce qu'un nouveau message soit envoyé au socket ou que le délai d'attente soit atteint (le cas échéant) | si un message a été envoyé et déjà mis en file d'attente dans le tampon du socket avant d'appeler la fonction de réception, ce message est renvoyé, sinon un message vide est renvoyé. |
envoyer un nouveau message (tcp et udp) | Dans le cas où le buffer du socket n'est pas plein et peut héberger entièrement le message à envoyer, le message est effectivement écrit dans le buffer et la fonction retourne quasi instantanément. Dans le cas contraire, le thread appelant est absorbé jusqu'à ce que l'espace soit occupé dans le tampon (car les messages sont consommés de l'autre côté), après quoi le message est réellement écrit et la fonction se termine. | S'il y a suffisamment d'espace dans le tampon du socket, le message est écrit et la fonction retourne. Dans le cas contraire, la fonction renvoie immédiatement sans réellement envoyer le message (l'envoi peut être retenté ultérieurement) |
Vous n'avez pas déjà quitté une étoile ? Faites-le maintenant ;) !
Pour créer un serveur TCP bloquant classique, il vous suffit de créer un objet tcp::TcpServer :
# include < MinimalSocket/tcp/TcpServer.h >
MinimalSocket::Port port = 15768 ; // the port to bind
MinimalSocket::tcp::TcpServer< true > tcp_server (
port, MinimalSocket::AddressFamily::IP_V4);
ouvrez-le :
// open the server: binds the port and start to listen on the port
bool success = tcp_server.open();
et maintenant vous êtes prêt à accepter de nouveaux clients :
// accepts the next client that will ask the connection
MinimalSocket::tcp::TcpConnectionBlocking accepted_connection =
tcp_server.acceptNewClient(); // blocking till a client actually asks the
// connection
vous pouvez maintenant échanger des messages avec le client accepté en faisant simplement ceci :
// receive a message
std:: size_t message_max_size = 1000 ;
std::string
received_message // resized to the nunber of bytes actually received
= accepted_connection.receive(message_max_size);
// send a message
accepted_connection.send( " a message to send " );
Si vous avez plutôt besoin d'un serveur non bloquant, vous pouvez le créer de la même manière :
MinimalSocket::Port port = 15768 ; // the port to bind
MinimalSocket::tcp::TcpServer< false > tcp_server (
port, MinimalSocket::AddressFamily::IP_V4);
tcp_server.open();
Cette version du serveur sera non bloquante, ce qui signifie que la fonction accept retournera immédiatement :
// check if a client asked for the connection. If no, the function immediately
// returns a nullopt. On the contrary, the returned optional contains the
// handler to the connected client
std::optional<MinimalSocket::tcp::TcpConnectionBlocking>
maybe_accepted_connection = tcp_server.acceptNewClient();
Notez que même si le serveur en soi n'est pas bloquant, le gestionnaire client finalement accepté bloque. Vous pouvez également le transformer en socket non bloquant, en transférant le socket vers un gestionnaire non bloquant :
MinimalSocket::tcp::TcpConnectionNonBlocking accepted_connection_nn_block =
maybe_accepted_connection-> turnToNonBlocking ();
Pour créer un client TCP, il vous suffit de créer un objet tcp::TcpClient :
# include < MinimalSocket/tcp/TcpClient.h >
MinimalSocket::Port server_port = 15768 ;
std::string server_address = " 192.168.125.85 " ;
MinimalSocket::tcp::TcpClient< true > tcp_client (
MinimalSocket::Address{server_address, server_port});
ouvrez-le :
// Open the server. Here, the client will ask the connection to specified
// server. After that, the client will be actually connected.
bool success =
tcp_client.open(); // blocking till the connection is actually established
vous pouvez désormais recevoir et envoyer des informations avec le serveur distant en faisant simplement ceci :
// send a message
tcp_client.send( " a message to send " );
// receive a message
std:: size_t message_max_size = 1000 ;
std::string
received_message // resized to the nunber of bytes actually received
= tcp_client.receive(message_max_size);
Si vous avez plutôt besoin d'un client non bloquant, vous pouvez le créer et l'utiliser de la même manière :
MinimalSocket::Port server_port = 15768 ;
std::string server_address = " 192.168.125.85 " ;
MinimalSocket::tcp::TcpClient< false > tcp_client (
MinimalSocket::Address{server_address, server_port});
tcp_client.open();
std:: size_t message_max_size = 1000 ;
// non blocking receive: returns immediately with an empty message in case no
// new data were available, or with a non empty message in the contrary case
std::string received_message = tcp_client.receive(message_max_size);
Pour créer un socket udp normal, il vous suffit de créer un objet udp::Udp :
# include < MinimalSocket/udp/UdpSocket.h >
MinimalSocket::Port this_socket_port = 15768 ;
MinimalSocket::udp::Udp< true > udp_socket (this_socket_port,
MinimalSocket::AddressFamily::IP_V6);
ouvrez-le :
// Open the server. This will bind the specified port.
bool success = udp_socket.open();
vous pouvez désormais recevoir et envoyer des informations avec d'autres sockets udp :
// send a message to another udp
MinimalSocket::Address other_recipient_udp =
MinimalSocket::Address{ " 192.168.125.85 " , 15768 };
udp_socket.sendTo( " a message to send " , other_recipient_udp);
// receive a message from another udp reaching this one
std:: size_t message_max_size = 1000 ;
auto received_message = udp_socket.receive(message_max_size);
// check the sender address
MinimalSocket::Address other_sender_udp = received_message->sender;
// access the received message
std::string received_message_content // resized to the nunber of bytes
// actually received
= received_message->received_message;
vous pouvez également décider de "connecter" un socket udp ouvert à une adresse spécifique. Attention, cela signifie simplement que les messages provenant d'autres pairs seront filtrés, car les sockets udp ne sont pas orientées connexion :
MinimalSocket::Address permanent_sender_udp =
MinimalSocket::Address{ " 192.168.125.85 " , 15768 };
MinimalSocket::udp::UdpConnected< true > udp_connected_socket =
udp_socket.connect(
permanent_sender_udp); // ownership of the underlying socket is
// transfered from udp_socket to
// udp_connected_socket, meaning that you can't
// use anymore udp_socket (unless you re-open
// it)
Vous pouvez désormais envoyer et recevoir des données sans avoir à spécifier le destinataire/l'expéditeur :
// receive a message
std:: size_t message_max_size = 1000 ;
std::string
received_message // resized to the nunber of bytes actually received
= udp_connected_socket.receive(message_max_size);
// send a message
udp_connected_socket.send( " a message to send " );
Vous pouvez également créer et utiliser des sockets udp non bloquantes :
MinimalSocket::Port this_socket_port = 15768 ;
MinimalSocket::udp::Udp< false > udp_socket (
this_socket_port, MinimalSocket::AddressFamily::IP_V6);
udp_socket.open();
std:: size_t message_max_size = 1000 ;
// non blocking receive: returns immediately with an empty message in case no
// new data were available, or with a non empty message in the contrary case
//
// struct ReceiveStringResult {
// Address sender;
// std::string received_message;
// };
std::optional<MinimalSocket::ReceiveStringResult> received_message =
udp_socket.receive(message_max_size);
Vous n'avez pas déjà quitté une étoile ? Faites-le maintenant ;) !
Des exemples d'utilisation des sockets TCP peuvent être trouvés ici, tandis que des exemples udp sont discutés ici.
ATTENTION!!! L'exécution des exemples peut être bloquée la première fois par votre pare-feu : configurez correctement votre pare-feu ou exécutez les exemples avec les privilèges d'administrateur.
Vous n'avez pas déjà quitté une étoile ? Faites-le maintenant ;) !
Pour consommer cette bibliothèque, vous pouvez compter sur CMake. Plus précisément, vous pouvez récupérer ce package et créer un lien vers la bibliothèque MinimalSocket :
include (FetchContent)
set (BUILD_MinimalCppSocket_SAMPLES OFF CACHE BOOL "" FORCE) # you don't want the samples in this case
FetchContent_Declare(
min_sock
GIT_REPOSITORY https://github.com/andreacasalino/Minimal-Socket
GIT_TAG master
)
FetchContent_MakeAvailable(min_sock)
puis créez un lien vers la bibliothèque MinimalSocket :
target_link_libraries ( ${TARGET_NAME}
MinimalSocket
)
Tous les modules spécifiques au système sont inclus en interne et ne sont pas exposés. De plus, sous Windows , wsock32 et ws2_32 sont liés de manière privée et vous n'avez pas besoin de les lier à nouveau lors de la consommation de MinimalSocket .