tcpclient_web_logo

TcpClient C++ library

v1.2.1

Table of contents

Overview

TcpClient C++ library provides methods to work with TCP socket as client (connect, close, send data and receive data). TcpClient library is cross-platform and compatible with Windows and Linux OS. The library utilizes C++17 standard and doesn’t have any third-party dependencies. Main file TcpClient.h includes declaration of TcpClient class which provides methods to work with TCP socket as a client.

Versions

Table 1 - Library versions.

Version Release date What’s new
1.0.0 17.05.2023 First version.
1.1.0 13.10.2023 - Add local port configuration support.
1.1.1 30.10.2023 - Fixed local port bind issue.
1.1.2 06.03.2024 - Documentation updated.
1.1.3 16.04.2024 - Documentation updated.
1.1.4 22.05.2024 - Documentation updated.
1.2.0 29.07.2024 - CMake structure updated.
- Implementation code moved to separate folder.
1.2.1 18.11.2024 - Disable SIGPIPE signal.

Library files

The library is supplied only by source code. The user is given a set of files in the form of a CMake project (repository). The repository structure is shown below:

CMakeLists.txt ------------- Main CMake file of the library.
src ------------------------ Folder with library source code.
    CMakeLists.txt --------- CMake file of the library.
    TcpClient.h ------------ Main library header file.
    TcpClient.cpp ---------- C++ class definitions file.
    TcpClientVersion.h ----- Header file with library version.
    TcpClientVersion.h.in -- File for CMake to generate version header.
    impl
        TcpClientImpl.h ----- Library implementation header file.
        TcpClientImpl.cpp --- C++ implementation file.
test ----------------------- Folder for test application.
    CMakeLists.txt --------- CMake file of test application.
    main.cpp --------------- Source code of test application.

TcpClient class description

Class declaration

TcpClient class declared in TcpClient.h file. Class declaration:

class TcpClient
{
public:

    /// Class constructor.
    TcpClient();

    /// Class destructor.
    ~TcpClient();

    /// Get current class version string.
    static std::string getVersion();

    /// Connect to server.
    bool connect(std::string ip, int serverPort, int timeoutMsec = 100, int clientPort = -1);

    /// Get connection status.
    bool isConnected();

    /// Close connection.
    void close();

    /// Send data to server.
    int send(uint8_t* data, int size);

    /// Read data from server.
    int read(uint8_t* data, int size);
};

getVersion method

The getVersion() method return string of current class version. Method declaration:

static std::string getVersion();

Method can be used without TcpClient class instance:

std::cout << "TcpClient version: " << cr::clib::TcpClient::getVersion();

Console output:

TcpClient version: 1.2.0

connect method

The connect(…) method initializes TCP connection to server. Method declaration:

bool connect(std::string ip, int serverPort, int timeoutMsec = 100, int clientPort = -1);
Parameter Value
ip IP address of TCP server.
serverPort TCP server port. Must have values from 0 to 65535.
timeoutMsec Wait data timeout. Method sets timeout to TCP socket properties. Timeout determines behavior of read(…) method: method will wait input data maximum timeoutMsec milliseconds and will return negative results if no input data.
clientPort TCP client port. Must have values from 0 to 65535. If set to -1 the library will chose port itself.

Returns: TRUE if connection done or FALSE if not.

read method

The read(…) method designed to read (wait) input data. After receiving input data the method will return control immediately or will return control after timeout (set connect(…) method) if no input data. Method declaration:

int read(uint8_t* data, int size);
Parameter Value
data Pointer to data buffer.
size Size of data buffer and maximum data size to read from socket.

Returns: Number of bytes or -1 if no input data or timeout expired (set in open(…) method) or UDP socket not open.

send method

The send(…) sends data. Method declaration:

int send(uint8_t* data, int size);
Parameter Value
data Pointer to data buffer.
size Size of data to send.

Returns: Number of bytes sent or -1 if data not sent (no connection or others errors).

isConnected method

The isConnected() method returns TCP connections status. Method declaration:

bool isConnected();

Returns: TRUE if TCP client connected to server or FALSE if not.

close method

The close() method designed to close connection if it open. Method declaration:

void close();

Build and connect to your project

Typical commands to build TcpClient library:

cd TcpClient 
mkdir build
cd build
cmake ..
make

If you want connect TcpClient library to your CMake project as source code you can make follow. For example, if your repository has structure:

CMakeLists.txt
src
    CMakeList.txt
    yourLib.h
    yourLib.cpp

Create folder 3rdparty and copy folder of TcpClient repository there. New structure of your repository:

CMakeLists.txt
src
    CMakeList.txt
    yourLib.h
    yourLib.cpp
3rdparty
    TcpClient

Create CMakeLists.txt file in 3rdparty folder. CMakeLists.txt should contain:

cmake_minimum_required(VERSION 3.13)

################################################################################
## 3RD-PARTY
## dependencies for the project
################################################################################
project(3rdparty LANGUAGES CXX)

################################################################################
## SETTINGS
## basic 3rd-party settings before use
################################################################################
# To inherit the top-level architecture when the project is used as a submodule.
SET(PARENT ${PARENT}_YOUR_PROJECT_3RDPARTY)
# Disable self-overwriting of parameters inside included subdirectories.
SET(${PARENT}_SUBMODULE_CACHE_OVERWRITE OFF CACHE BOOL "" FORCE)

################################################################################
## CONFIGURATION
## 3rd-party submodules configuration
################################################################################
SET(${PARENT}_SUBMODULE_TCP_CLIENT                      ON  CACHE BOOL "" FORCE)
if (${PARENT}_SUBMODULE_TCP_CLIENT)
    SET(${PARENT}_TCP_CLIENT                            ON  CACHE BOOL "" FORCE)
    SET(${PARENT}_TCP_CLIENT_TEST                       OFF CACHE BOOL "" FORCE)
endif()

################################################################################
## INCLUDING SUBDIRECTORIES
## Adding subdirectories according to the 3rd-party configuration
################################################################################
if (${PARENT}_SUBMODULE_TCP_CLIENT)
    add_subdirectory(TcpClient)
endif()

File 3rdparty/CMakeLists.txt adds folder TcpClient to your project and excludes test application from compiling (by default test applications and example are excluded from compiling if TcpClient is included as sub-repository). The new structure of your repository:

CMakeLists.txt
src
    CMakeList.txt
    yourLib.h
    yourLib.cpp
3rdparty
    CMakeLists.txt
    TcpClient

Next you need include folder 3rdparty in main CMakeLists.txt file of your repository. Add string at the end of your main CMakeLists.txt:

add_subdirectory(3rdparty)

Next you have to include TcpClient library in your src/CMakeLists.txt file:

target_link_libraries(${PROJECT_NAME} TcpClient)

Done!

Example

Test application shows how to create TCP client and connect to server. The application trying connect to server after start or trying connect to server if connection disappears.

#include <iostream>
#include <chrono>
#include <ctime>
#include <thread>
#include "TcpClient.h"



int main(void)
{
    std::cout << "TcpClient v" << cr::clib::TcpClient::getVersion() << " test" << std::endl;

    std::string ip = "";
    std::cout << "Set TCP server IP: ";
    std::cin >> ip;

    int serverPort = 0;
    std::cout << "Enter server port: ";
    std::cin >> serverPort;

    int clientPort = 0;
    std::cout << "Enter client port: ";
    std::cin >> clientPort;

    // Create client and connect to server.
    cr::clib::TcpClient client;
    while (!client.connect(ip, serverPort, 500, clientPort))
    {
        std::cout << "Can't connect to server" << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        continue;
    }

    // Main loop.
    const int numBytes = 128;
    uint8_t data[numBytes];
    while (true)
    {
        // Check connection.
        if (!client.isConnected())
        {
            // Connect to CommsManager. 4 msec wait data timeout.
            if (!client.connect(ip, serverPort, 500, clientPort))
            {
                std::cout << "Can't connect to server" << std::endl;
                std::this_thread::sleep_for(std::chrono::milliseconds(1000));
                continue;
            }
        }

        // Prepare random data.
        for (int i = 0; i < numBytes; ++i)
        {
            data[i] = (uint8_t)(rand() % 255);
        }

        // Send data to server.
        std::cout << client.send(data, numBytes) << " bytes sent" << std::endl;

        // Wait response.
        int bytes = client.read(data, numBytes);

        // Check result.
        if (bytes <= 0)
        {
            std::cout << "No response from server" << std::endl;
        }
        else
        {
            std::cout << bytes << " bytes received" << std::endl;
        }
    }
    return 1;
}