I needed to perform network communications in my Linux C++ project. I thought that it was a good idea to operate on a higher level of abstraction than raw system calls. Also I love OO design. So I'm implementing an object-oriented high-level Unix network open-source library (There are issues with tab-size if you watch source code on github, but the tabs are aligned well if watching in a text editor).
At the moment the library is partially implemented and is in a process of development. I've already tested some parts of it in real project and I find it's high level of abstraction extremely convenient.
The library checks all system calls for errors, so user shouldn't worry about checking every function's return status (thou exception system is still under construction). It allows easily convert socket addresses and strings in both directions. Socket classes provide convenient methods to get and set their properties, messages are sent and received as strings. TCP socket can recieve messages separated by terminator character or messages determined by required message size e.t.c.
I would like to know community's opinion if I made some design or implementation mistakes, if there could be done some improvements and if the library could be useful in some way to somebody. Any feedback is appreciated.
Here is a working example of a UDP echo-server implementation using my library.
#include <iostream>
#include <Unet/UdpSocket.hpp>
#include <Unet/Ipv4Address.hpp>
int main ( int argc , char** argv )
{
// Check program parameters to be provided
if ( argc != 3 )
{
std::cout << "Usage: UdpEchoServer $(SERVER_IP) $(SERVER_PORT)" << std::endl;
return -1;
}
// Create and open UDP socket with Internet family address
Unet::UdpSocket socket;
socket.open();
std::cout << "Server socket was opened successfully." << std::endl;
// Set server socket to reuse address
socket.setOption(SO_REUSEADDR,1);
std::cout << "Server socket option \"SO_REUSEADDR\" was set to \"1\"." << std::endl;
// Bind socket to the specified local address
socket.bind(Unet::Ipv4Address(argv[1],argv[2]));
std::cout << "Server socket was bound successfully." << std::endl;
// Datagram which will be recieved and sent back
Unet::Datagram datagram;
while ( true )
{
try
{
if ( socket.hasUnreadData() )
{
// Recieve incomming datagram
datagram = socket.recieveDatagram();
std::cout << "[ <-- ] [" << Unet::Ipv4Address(datagram.address).toString() << "] - " << datagram.message << std::endl;
// And send it back
socket.sendDatagram(datagram);
std::cout << "[ --> ] [" << Unet::Ipv4Address(datagram.address).toString() << "] - " << datagram.message << std::endl;
}
}
// Catch and print all exceptions
catch ( Unet::Exception exception )
{
std::cout << "Unet exception: " << exception.getMessage() << std::endl;
}
catch ( std::exception exception )
{
std::cout << "Standard exception: " << exception.what() << std::endl;
}
catch ( ... )
{
std::cout << "Unknown exception" << std::endl;
}
}
}
P.S. I'm not a Linux specialist, so I doubt which name to choose for the library Unix-net
, Linux-net
or Posix-net
. Which is more appropriate and logical?