A ServerSocket and Socket library for Windows and Linux aiming to support both Wifi and Bluetooth communication.
- CMake and
make
The following linux dependencies are required:
libbluetooth-dev
libglib2.0-dev
bluez
- To build the library, firstly run cmake:
cmake . -B build-linux
in the root directory of the repository (CppSocketLibrary/
). - Then move into the new
build-linux
folder:cd build-linux
. - Then you can run
make
to build the library. - Then you can run
make check
to run the available tests.
- To build the library, firstly run cmake:
cmake . -B build
in the root directory of the repository (CppSocketLibrary/
). - This will create a
.sln
file which can be opened inVisual Studio
. - Once opened (and with the appropriate windows service packs installed -
MSVC v143 - VS 2022 C++ x64/x86 Spectre-mitigated libs (v14.29-16.11)
) - You can then build and run the
CppSocketLibraryTest
project and it will rebuild the library and run the appropriate tests.
- TCP Example using IPV6:
void tcpExample()
{
// Create a new Wifi ServerSocket
kt::ServerSocket server(kt::SocketType::Wifi, 56756, 20, kt::InternetProtocolVersion::IPV6);
// Create new TCP socket
kt::TCPSocket client("::1", server.getPort());
// Accept the incoming connection at the server
kt::TCPSocket serverSocket = server.acceptTCPConnection();
// Send string with text before and after the delimiter
const std::string testString = "TCP Delimiter Test";
const char delimiter = '~';
if (!client.send(testString + delimiter + "other string").first)
{
std::cout << "Failed to send test string" << std::endl;
return;
}
if (serverSocket.ready())
{
std::string response = serverSocket.receiveToDelimiter(delimiter);
// Check that the received string is the same as the string sent by the client
ASSERT_EQ(response, testString);
}
// Close all sockets
client.close();
serverSocket.close();
server.close();
}
- UDP Example using IPV4 (the default protocol version - so protocol related arguments are omitted):
void udpExample()
{
// The socket receiving data must first be bound
kt::UDPSocket socket;
socket.bind(37893, kt::InternetProtocolVersion::IPV4);
kt::UDPSocket client;
const std::string testString = "UDP test string";
if (!client.sendTo("localhost", 37893, testString).first.first)
{
std::cout << "Failed to send to address." << std::endl;
return;
}
if (socket.ready())
{
std::pair<std::optional<std::string>, std::pair<int, kt::SocketAddress>> recieved = socket.receiveFrom(testString.size());
ASSERT_EQ(testString, recieved.first.value());
}
socket.close();
}
SIGPIPE
is a signal error raised by UNIX when you attempt to write data to a closed linux socket (closed by the remote). There are a few ways to work around this signal. Note: that in both cases, the kt::TCPSocket.send()
function will return false
in the result pair so you can detect that the send has failed. (You can refer to the TCPSocketTest.cpp file and the "...Linux..." related tests to do with "SIGPIPE" to find examples of the below).
- Ignore SIGPIPE signals completely:
#include <csignal>
int main()
{
std::signal(SIGPIPE, SIG_IGN);
...
}
- Provide
MSG_NOSIGNAL
as theflag
argument to thekt::TCPSocket.send()
function which will ensure no signals are raised during thekt::TCPSocket.send()
call.
#include <csignal>
...
kt::TCPSocket socket; // Initialise properly
...
if (!socket.send(std::string(message), MSG_NOSIGNAL).first)
{
// Remote has closed connection, you can choose to close the current socket or any other work that is required when the connection is broken
}
...
- Setup a handler function to be called with the
SIGPIPE
signal is raised.
#include <csignal>
void handleSignal(int signal)
{
if (signal == SIGPIPE)
{
...
}
}
int main()
{
// Set your handler function to be called when the signal is raised
std::signal(SIGPIPE, handleSignal);
...
// If you want to restore the default signal handling behaviour you can do the following
std::signal(SIGPIPE, SIG_DFL);
}
- Take care when reading UDP messages. If you do not read the entire length of the message the rest of the data will be lost.
The dockerfile is aimed at testing the socket behaviour across a few different flavours of linux to check it is functioning correctly. Especially since development is being done on WSL and there could be some slight differences.
docker build -f Environment-Test-Dockerfile .