A C++11 header-only, simple and easy cross-platform socket library.
- Supports TCP, UDP and Unix Domain Socket(UDS).
- It performs buffering internally(TCP,UDS).
- When all user data is received, the user-specified callback is called.
- No repeat send calls until all are sent. When send returns WSAEWOULDBLOCK / EWOULDBLOCK / EAGAIN, It will be added to the queue and sent later.
- Composition or Inheritance class usage.
- Using epoll (linux), kqueue (macOS) and winsock (windows).
- No additional dependencies required.
-
This is a header-only library, so you can just add the asock folder to your project include directory.
cp -r asock your_include_path/. -
Add below code to your CMake file
include(FetchContent) fetchcontent_declare( asock GIT_REPOSITORY https://github.com/jeremyko/ASockLib GIT_TAG fa7b362998157972b48b2c30042d0c13c8557bfc #1.0.7 ) fetchcontent_makeavailable(asock) -
Option 3: Using vcpkg
vcpkg install asock -
The test code has a googletest dependency. If you are simply installing asock, no test code compilation is required. The sample code has no dependencies, but is not required for asock installation. That's why
DJEREMYKO_ASOCK_BUILD_TESTS=OFFand-DJEREMYKO_ASOCK_BUILD_SAMPLES=OFFare used.mkdir build cd build cmake .. -DJEREMYKO_ASOCK_BUILD_TESTS=OFF -DJEREMYKO_ASOCK_BUILD_SAMPLES=OFF sudo make installfind_package(asock CONFIG REQUIRED) target_link_libraries(yours PRIVATE asock::asock)
The following is a tcp echo example using class inheritance. See the sample folder for all examples. You can find composition usage and udp, domain socket example too.
//This is an inheritance usage. #include "asock/asock_tcp_server.hpp" #define DEFAULT_PACKET_SIZE 1024 class Server : public asock::ASockTcpServer { private: bool OnRecvedCompleteData(asock::Context* context_ptr, const char* const data_ptr, size_t len) override { //user specific : - your whole data has arrived. char packet[DEFAULT_PACKET_SIZE]; memcpy(&packet, data_ptr,len ); packet[len] = '\0'; std::cout << "recved [" << packet << "]\n"; if(! tcp_server_.SendData(context_ptr, data_ptr, len) ) { std::cerr << GetLastErrMsg() <<"\n"; return false; } return true; } void OnClientConnected(asock::Context* context_ptr) override { std::cout << "client connected : socket fd ["<< context_ptr->socket <<"]\n"; } void OnClientDisconnected(asock::Context* context_ptr) override { std::cout << "client disconnected : socket fd ["<< context_ptr->socket <<"]\n"; } }; int main(int argc, char* argv[]) { Server Server; if(!Server.RunTcpServer("127.0.0.1", 9990 )) { std::cerr << Server.GetLastErrMsg() <<"\n"; exit(EXIT_FAILURE); } std::cout << "server started" << "\n"; while( Server.IsServerRunning() ) { std::this_thread::sleep_for(std::chrono::seconds(1)); } std::cout << "server exit...\n"; exit(EXIT_SUCCESS); } //This is an inheritance usage. #include "asock/asock_tcp_client.hpp" #define DEFAULT_PACKET_SIZE 1024 class Client : public asock::ASockTcpClient { private: bool OnRecvedCompleteData(asock::Context* , const char* const data_ptr, size_t len) override { //user specific : - your whole data has arrived. char packet[DEFAULT_PACKET_SIZE]; memcpy(&packet,data_ptr ,len); packet[len] = '\0'; std::cout << "server response [" << packet << "]\n"; return true; } void OnDisconnectedFromServer() override { std::cout << "server disconnected, terminate client\n"; client_.Disconnect(); } }; int main(int argc, char* argv[]) { Client client; if(!client.InitTcpClient("127.0.0.1", 9990 ) ) { std::cerr << client.GetLastErrMsg() <<"\n"; exit(EXIT_FAILURE); } std::string user_msg {""}; while( client.IsConnected() ) { std::cin.clear(); getline(std::cin, user_msg); int msg_len = user_msg.length(); if(msg_len>0) { if(! client.SendToServer(user_msg.c_str(), msg_len) ) { std::cerr << client.GetLastErrMsg() <<"\n"; exit(EXIT_FAILURE); } } } //while exit(EXIT_SUCCESS); }