Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cross-platform sockets

Tags:

c

sockets

I know, Windows doesn't use UNIX sockets while Mac OS does. Until this point my software was cross-platform without any code changes. But now I want it to do some network communication. I know about POSIX sockets, but I know nothing about Windows' ones. The goal is to implement a simple cross-platform socket server.

Could you please explain to me the differences between POSIX and Winsock sockets and how I may go about writing cross platform networking code?

like image 638
ForceBru Avatar asked Jan 19 '15 15:01

ForceBru


People also ask

What is the best library to use for cross platform sockets?

There are many libraries and toolkits that support cross platform sockets, depending on what you are doing, you can use (to name a few): openssl apache portable runtime libtcl

What sockets do I need to build a socket server?

The regular sockets (those in AF_INET address family) which you need to build a socket server are equally supported on all platforms. Do not confuse them with Unix sockets (those in AF_UNIX address family) - such sockets are highly specific for a Unix world, and are used for a highly specific goals.

What is the best C++ library for sockets and threads?

Ptlib provides cross platform C++ code that works well for sockets. www.opalvoip.org Copes nicely with threads. Some support for mac and BSD.

Is there a library similar to socket programming in Linux?

I don't know one library that complies both Windows and Linux but I think winsock is similar enough to Linux socket programming. In particular it supplies you 'select ()' and the other functions mentioned. I guess you will need a very thin #ifdef wrapper to avoid type casting warnings.


4 Answers

WinSock versus POSIX Sockets

WinSock and POSIX sockets work in a similar manner - mainly because Windows sockets were originally based on code from BSD:

Although these proprietary BSD derivatives were largely superseded by the UNIX System V Release 4 and OSF/1 systems in the 1990s (both of which incorporated BSD code and are the basis of other modern Unix systems), later BSD releases provided a basis for several open source development projects, e.g. FreeBSD, OpenBSD, NetBSD, Darwin or PC-BSD, that are ongoing. These, in turn, have been incorporated in whole or in part in modern proprietary operating systems, e.g. the TCP/IP (IPv4 only) networking code in Microsoft Windows and most of the foundation of Apple's OS X and iOS.

However, there are a few things you'll need to handle differently if you want to write "socket-library-agnostic" code.

Note: The following examples have been tested using Code::Blocks and GCC on Windows XP (x86) and Debian Testing (AMD64).

The header and lib files are different

You'll need to include different header files depending on whether you're using Windows or not:

#ifdef _WIN32
  /* See http://stackoverflow.com/questions/12765743/getaddrinfo-on-win32 */
  #ifndef _WIN32_WINNT
    #define _WIN32_WINNT 0x0501  /* Windows XP. */
  #endif
  #include <winsock2.h>
  #include <Ws2tcpip.h>
#else
  /* Assume that any non-Windows platform uses POSIX-style sockets instead. */
  #include <sys/socket.h>
  #include <arpa/inet.h>
  #include <netdb.h>  /* Needed for getaddrinfo() and freeaddrinfo() */
  #include <unistd.h> /* Needed for close() */
#endif

You'll also need to link with Ws2_32 lib file on Windows.

WinSock requires initialisation and cleanup.

The functions below illustrate how you can initialise WinSock v1.1 and clean up afterwards:

int sockInit(void)
{
  #ifdef _WIN32
    WSADATA wsa_data;
    return WSAStartup(MAKEWORD(1,1), &wsa_data);
  #else
    return 0;
  #endif
}

int sockQuit(void)
{
  #ifdef _WIN32
    return WSACleanup();
  #else
    return 0;
  #endif
}

Socket handles are UNSIGNED on Winsock

For POSIX-style sockets, you can simply use int to store a socket handle. Invalid sockets are indicated by a negative value.

However, WinSock sockets are UNSIGNED integers, with a special constant (INVALID_SOCKET) used instead of negative numbers.

You can abstract the differences by typedefing SOCKET as int on POSIX and hiding the "valid socket" check behind a macro or function.

Sockets are closed differently

The function below illustrates the differences:

/* Note: For POSIX, typedef SOCKET as an int. */

int sockClose(SOCKET sock)
{

  int status = 0;

  #ifdef _WIN32
    status = shutdown(sock, SD_BOTH);
    if (status == 0) { status = closesocket(sock); }
  #else
    status = shutdown(sock, SHUT_RDWR);
    if (status == 0) { status = close(sock); }
  #endif

  return status;

}

In general though, they're pretty similar.

If you stick to "common" functions (such as send() or recv()) and avoid platform-specific stuff (such as WSAWaitForMultipleEvents()) then you should be fine.

like image 97
GoBusto Avatar answered Oct 21 '22 07:10

GoBusto


I can also suggest the plibsys library: works on both Windows and UNIX systems (see the full list on the project page) with various compilers. Supports IPv4 and IPv6. It has the tests where you can see the usage examples. The library itself is lightweight and portable.

like image 44
Alexander Saprykin Avatar answered Oct 21 '22 07:10

Alexander Saprykin


There are many libraries and toolkits that support cross platform sockets, depending on what you are doing, you can use (to name a few):

  • openssl
  • apache portable runtime
  • libtcl

If you don't want to have a dependency on an external library, all of the above packages have fairly permissive licenses, so you can use their code as a reference.

like image 30
GNSL Avatar answered Oct 21 '22 07:10

GNSL


The regular sockets (those in AF_INET address family) which you need to build a socket server are equally supported on all platforms.

Do not confuse them with Unix sockets (those in AF_UNIX address family) - such sockets are highly specific for a Unix world, and are used for a highly specific goals. You wouldn't ever need them for a simple socket server application.

like image 42
user58697 Avatar answered Oct 21 '22 09:10

user58697