{"id":18770099,"url":"https://github.com/andreacasalino/minimal-socket","last_synced_at":"2025-04-07T15:11:14.096Z","repository":{"id":39988172,"uuid":"271771976","full_name":"andreacasalino/Minimal-Socket","owner":"andreacasalino","description":"Minimal cross platform C++ tcp, udp socket implementation","archived":false,"fork":false,"pushed_at":"2024-11-20T13:33:01.000Z","size":1033,"stargazers_count":68,"open_issues_count":2,"forks_count":13,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-31T14:11:55.188Z","etag":null,"topics":["cpp","cpp17","cross-platform","crossplatform","google-protobuf","socket","socket-io","socket-programming","tcp","tcp-client","tcp-server","udp","udp-client","udp-server","winsock","winsock2"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/andreacasalino.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-06-12T10:31:25.000Z","updated_at":"2025-03-14T16:53:52.000Z","dependencies_parsed_at":"2024-03-17T22:28:39.041Z","dependency_job_id":"f346036c-5120-4469-b49c-f4b36464fb86","html_url":"https://github.com/andreacasalino/Minimal-Socket","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andreacasalino%2FMinimal-Socket","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andreacasalino%2FMinimal-Socket/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andreacasalino%2FMinimal-Socket/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andreacasalino%2FMinimal-Socket/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/andreacasalino","download_url":"https://codeload.github.com/andreacasalino/Minimal-Socket/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247675607,"owners_count":20977378,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cpp","cpp17","cross-platform","crossplatform","google-protobuf","socket","socket-io","socket-programming","tcp","tcp-client","tcp-server","udp","udp-client","udp-server","winsock","winsock2"],"created_at":"2024-11-07T19:18:07.833Z","updated_at":"2025-04-07T15:11:14.075Z","avatar_url":"https://github.com/andreacasalino.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"![binaries_compilation](https://github.com/andreacasalino/Cross-Platform-Socket/actions/workflows/runTests.yml/badge.svg)\r\n\r\n- [What is this library about](#intro)\r\n- [Features](#features)\r\n- [Usage](#usage)\r\n- [Samples](#samples)\r\n- [CMake support](#cmake-support)\r\n\r\n![Sockets](./sockets.png)\r\n\r\n## INTRO\r\n\r\n**MinimalSocket** gives you a modern **C++** library to set up and create **tcp** and **udp** socket connections, in a\r\ncompletely platform agnostic way. The supported systems are: **Windows**, any **Linux** distro and **MacOS**.\r\n\r\nThe [Features](#features) Section details the various features of **MinimalSocket**. Read [Usage](#usage) and [Samples](#samples) to see how easy is to use **MinimalSocket**.\r\n\r\nThis is a **CMake** project, check [CMake support](#cmake-support) to see how this library can be integrated.\r\n\r\nRemember to leave a **star** in case you have found this library useful.\r\n\r\n## FEATURES\r\n\r\nHaven't left a **star** already? Do it now ;)!\r\n\r\n**MinimalSocket** allows you to build and set up **tcp** and **udp** connections. Messages can be sent and received in terms of both buffer of bytes or strings. Indeed, this is actually the only capability you need for a socket, as more complex messages can be serialized into or internalized from a buffer of bytes using, among the others, approaches like [Google Protocol Buffers](https://developers.google.com/protocol-buffers/docs/cpptutorial) or [NanoPb](https://jpa.kapsi.fi/nanopb/).\r\n\r\nThese are the most notable characteristics of **MinimalSocket**:\r\n- A modern **C++** object oriented API allowing you to set up and build socket connections. Typically, sockets are represented by the classes part of this library. Any time an object is created, the related socket is generated in a closed state in order to defer the opening at the convenient moment. This allows you to decouple the moments when sockets are created from those when the socket should be actually started and used. At the same time, any connection is automatically closed when the handler object is destroyed (and all relevant information cleaned up).\r\n- Prevent you from handling low level socket programming, abstracting from the particular platform hosting your application(s): let **MinimalSocket** do all the work for you. Morevoer, all the system specific modules, functions, linkages (ex. winsock in **Windows**) are not exposed.\r\n- **AF_INET** (**ip v4**) and **AF_INET6** (**ip v6**) addresses, refer to [this](https://www.ibm.com/docs/en/i/7.1?topic=characteristics-socket-address-family) link, are both supported\r\n- For any socket type, **MinimalSocket** allows you to choose between a blocking and a non blocking version (see also the table at the end of this Section as well as the [Usage](#usage) Section). In essence, non blocking sockets functions return always instantaneously, with some kind of result when succeeding or an empty result when failing. On the contrary, blocking sockets absorb the caller till the function can be actually completed. At the same time, it is also possible to specify some timeout for blocking socket after which the completion of the function is considered failed.\r\n- **MinimalSocket** is tested to be **thread safe**. However, notice that for a ceratin socket you can still send while receiving from different threads. This allows you to easily create your own asynchronous sockets, building on top of the classes offered by this library.\r\n- Under **Windows**, [**WSAStartup**](https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-wsastartup) is automatically called before using any relevant functionalities. If you need, it is also possible to specify the Windows Sockets to use.\r\n\r\nThis table summarizes the differences between the blocking and the non blocking behaviours of the socket that can be created using **MinimalSocket**:\r\n| | Blocking Behaviour, caller is blocked till completion or timeout is reached (if one was specified) | Non Blocking Behaviour, functions return immediately |\r\n| --- | --- | --- |\r\n| accepting of a new client (tcp only) | caller thread is absorbed till a new client actually asks to connect or timeout is reached (if any was specified) | if a connection request from a client was already queued before calling the accept function, a new connection handler is returned, otherwise a nullopt is returned. |\r\n| receive a new message (tcp and udp) | caller thread is absorbed till a new a message is sent to the socket or timeout is reached (if any was specified) | if a message was sent and already queued in the socket buffer before calling the receive function, that message is returned, otherwise an empty message is returned. |\r\n| send a new message (tcp and udp) | In case the buffer of the socket is not full and can entirely host the message to send, the message is actaully written in the buffer and the function returns almost instantaneously. On the contrary case, caller thread is absorbed until space is done in the buffer (as messages are consumed from the other side) and after that the message is actually written and function completes. | If there is enough space in the buffer of the socket, the message is written and the function returns. In the contrary case, the function returns immediately without actually send the message (the send can be retried later) |\r\n\r\n## USAGE\r\n\r\nHaven't left a **star** already? Do it now ;)!\r\n\r\n### TCP\r\n\r\n#### SERVER\r\n\r\nTo create a classic blocking **tcp** server you just need to build a **tcp::TcpServer** object:\r\n```cpp\r\n#include \u003cMinimalSocket/tcp/TcpServer.h\u003e\r\n\r\nMinimalSocket::Port port = 15768; // the port to bind\r\nMinimalSocket::tcp::TcpServer\u003ctrue\u003e tcp_server(\r\n    port, MinimalSocket::AddressFamily::IP_V4);\r\n```\r\n\r\nopen it:\r\n```cpp\r\n// open the server: binds the port and start to listen on the port\r\nbool success = tcp_server.open();\r\n```\r\n\r\nand now you are ready to accept new clients:\r\n```cpp\r\n// accepts the next client that will ask the connection\r\nMinimalSocket::tcp::TcpConnectionBlocking accepted_connection =\r\n    tcp_server.acceptNewClient(); // blocking till a client actually asks the\r\n                                // connection\r\n```\r\n\r\nyou can now exhange messages with the accepted client by simply doing this:\r\n```cpp\r\n// receive a message\r\nstd::size_t message_max_size = 1000;\r\nstd::string\r\n    received_message // resized to the nunber of bytes actually received\r\n    = accepted_connection.receive(message_max_size);\r\n// send a message\r\naccepted_connection.send(\"a message to send\");\r\n```\r\n\r\nIf you instead need a non blocking server, you can create it in a similar way:\r\n```cpp\r\nMinimalSocket::Port port = 15768; // the port to bind\r\nMinimalSocket::tcp::TcpServer\u003cfalse\u003e tcp_server(\r\n    port, MinimalSocket::AddressFamily::IP_V4);\r\ntcp_server.open();\r\n```\r\n\r\nThis server version will be non blocking, meaning that the accept function will return immediately:\r\n```cpp\r\n// check if a client asked for the connection. If no, the function immediately\r\n// returns a nullopt. On the contrary, the returned optional contains the\r\n// handler to the connected client\r\nstd::optional\u003cMinimalSocket::tcp::TcpConnectionBlocking\u003e\r\n    maybe_accepted_connection = tcp_server.acceptNewClient();\r\n```\r\n\r\nNotice that even though the server per se is non blocking, the eventually accepted client handler is blocking. \r\nYou can turn it to a non blocking socket too, by transferring the socket to a non blocking handler:\r\n```cpp\r\nMinimalSocket::tcp::TcpConnectionNonBlocking accepted_connection_nn_block =\r\n    maybe_accepted_connection-\u003eturnToNonBlocking();\r\n```\r\n\r\n#### CLIENT\r\n\r\nTo create a **tcp** client you just need to build a **tcp::TcpClient** object:\r\n```cpp\r\n#include \u003cMinimalSocket/tcp/TcpClient.h\u003e\r\n\r\nMinimalSocket::Port server_port = 15768;\r\nstd::string server_address = \"192.168.125.85\";\r\nMinimalSocket::tcp::TcpClient\u003ctrue\u003e tcp_client(\r\n    MinimalSocket::Address{server_address, server_port});\r\n```\r\n\r\nopen it:\r\n```cpp\r\n// Open the server. Here, the client will ask the connection to specified\r\n// server. After that, the client will be actually connected.\r\nbool success =\r\n    tcp_client.open(); // blocking till the connection is actually established\r\n```\r\n\r\nyou can now receive and send information with the remote server by simply doing this:\r\n```cpp\r\n// send a message\r\ntcp_client.send(\"a message to send\");\r\n// receive a message\r\nstd::size_t message_max_size = 1000;\r\nstd::string\r\n    received_message // resized to the nunber of bytes actually received\r\n    = tcp_client.receive(message_max_size);\r\n```\r\n\r\nIf you instead need a non blocking client you can create it ans use it in a similar way:\r\n```cpp\r\nMinimalSocket::Port server_port = 15768;\r\nstd::string server_address = \"192.168.125.85\";\r\nMinimalSocket::tcp::TcpClient\u003cfalse\u003e tcp_client(\r\n    MinimalSocket::Address{server_address, server_port});\r\ntcp_client.open();\r\n\r\nstd::size_t message_max_size = 1000;\r\n// non blocking receive: returns immediately with an empty message in case no\r\n// new data were available, or with a non empty message in the contrary case\r\nstd::string received_message = tcp_client.receive(message_max_size);\r\n```\r\n\r\n### UDP\r\n\r\nTo create a normal **udp** socket you just need to build a **udp::Udp** object:\r\n```cpp\r\n#include \u003cMinimalSocket/udp/UdpSocket.h\u003e\r\n\r\nMinimalSocket::Port this_socket_port = 15768;\r\nMinimalSocket::udp::Udp\u003ctrue\u003e udp_socket(this_socket_port,\r\n                                        MinimalSocket::AddressFamily::IP_V6);\r\n```\r\n\r\nopen it:\r\n```cpp\r\n// Open the server. This will bind the specified port.\r\nbool success = udp_socket.open();\r\n```\r\n\r\nyou can now receive and send information with other **udp** sockets:\r\n```cpp\r\n// send a message to another udp\r\nMinimalSocket::Address other_recipient_udp =\r\n    MinimalSocket::Address{\"192.168.125.85\", 15768};\r\nudp_socket.sendTo(\"a message to send\", other_recipient_udp);\r\n// receive a message from another udp reaching this one\r\nstd::size_t message_max_size = 1000;\r\nauto received_message = udp_socket.receive(message_max_size);\r\n// check the sender address\r\nMinimalSocket::Address other_sender_udp = received_message-\u003esender;\r\n// access the received message\r\nstd::string received_message_content // resized to the nunber of bytes\r\n                                    // actually received\r\n    = received_message-\u003ereceived_message;\r\n```\r\n\r\nyou can also decide to \"connect\" an opened **udp** socket to a specific address. Beware that this simply means that messages incoming from other peers will be filtered out, as **udp** sockets are not connection oriented:\r\n```cpp\r\nMinimalSocket::Address permanent_sender_udp =\r\n    MinimalSocket::Address{\"192.168.125.85\", 15768};\r\nMinimalSocket::udp::UdpConnected\u003ctrue\u003e udp_connected_socket =\r\n    udp_socket.connect(\r\n        permanent_sender_udp); // ownership of the underlying socket is\r\n                                // transfered from udp_socket to\r\n                                // udp_connected_socket, meaning that you can't\r\n                                // use anymore udp_socket (unless you re-open\r\n                                // it)\r\n```\r\n\r\nNow you can send and receive data without having to specify the recpient/sender:\r\n```cpp\r\n// receive a message\r\nstd::size_t message_max_size = 1000;\r\nstd::string\r\n    received_message // resized to the nunber of bytes actually received\r\n    = udp_connected_socket.receive(message_max_size);\r\n// send a message\r\nudp_connected_socket.send(\"a message to send\");\r\n```\r\n\r\nYou can also create and use non blocking **udp** sockets:\r\n```cpp\r\nMinimalSocket::Port this_socket_port = 15768;\r\nMinimalSocket::udp::Udp\u003cfalse\u003e udp_socket(\r\n    this_socket_port, MinimalSocket::AddressFamily::IP_V6);\r\nudp_socket.open();\r\n\r\nstd::size_t message_max_size = 1000;\r\n// non blocking receive: returns immediately with an empty message in case no\r\n// new data were available, or with a non empty message in the contrary case\r\n//\r\n// struct ReceiveStringResult {\r\n//   Address sender;\r\n//   std::string received_message;\r\n// };\r\nstd::optional\u003cMinimalSocket::ReceiveStringResult\u003e received_message =\r\n    udp_socket.receive(message_max_size);\r\n```\r\n\r\n## SAMPLES\r\n\r\nHaven't left a **star** already? Do it now ;)!\r\n\r\nExamples of usage about **tcp** sockets can be found [here](./samples/tcp/README.md), while **udp** samples are [here](./samples/udp/README.md) discussed.\r\n\r\nATTENTION!!! The Samples execution might be blocked the first time by your firewall: set up properly your firewall or run the samples with the [administrator privileges](https://www.techopedia.com/definition/4961/administrative-privileges#:~:text=Administrative%20privileges%20are%20the%20ability,as%20a%20database%20management%20system.)\r\n\r\n## CMAKE SUPPORT\r\n\r\nHaven't left a **star** already? Do it now ;)!\r\n   \r\nIn order to consume this library you can rely on [CMake](https://cmake.org).\r\nMore precisely, You can fetch this package and link to the **MinimalSocket** library:\r\n```cmake\r\ninclude(FetchContent)\r\nset(BUILD_MinimalCppSocket_SAMPLES OFF CACHE BOOL \"\" FORCE) # you don't want the samples in this case\r\nFetchContent_Declare(\r\nmin_sock\r\nGIT_REPOSITORY https://github.com/andreacasalino/Minimal-Socket\r\nGIT_TAG        master\r\n)\r\nFetchContent_MakeAvailable(min_sock)\r\n```\r\n\r\nand then link to the **MinimalSocket** library:\r\n```cmake\r\ntarget_link_libraries(${TARGET_NAME}\r\n    MinimalSocket\r\n)\r\n```\r\n\r\nAll the system specific modules are internally inlcluded and are not exposed.\r\nMoreover, under **Windows**, **wsock32** and **ws2_32** are privately linked and you don't need to link them again when consuming **MinimalSocket**.\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandreacasalino%2Fminimal-socket","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fandreacasalino%2Fminimal-socket","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandreacasalino%2Fminimal-socket/lists"}