views:

206

answers:

1

I'm new to C89, and trying to do some socket programming:

void get(char *url) {
    struct addrinfo *result;
    char *hostname;
    int error;

    hostname = getHostname(url);

    error = getaddrinfo(hostname, NULL, NULL, &result);

}

I am developing on Windows. Visual Studio complains that there is no such file if I use these include statements:

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

What should I do? Does this mean that I won't have portability to Linux?

+2  A: 

On Windows, instead of the includes you have mentioned, the following should suffice:

#include <winsock2.h>
#include <windows.h>

You'll also have to link to ws2_32.lib. It's kind of ugly to do it this way, but for VC++ you can do this via: #pragma comment(lib, "ws2_32.lib")

Some other differences between Winsock and POSIX include:

  • You will have to call WSAStartup() before using any socket functions.

  • close() is now called closesocket().

  • Instead of passing sockets as int, there is a typedef SOCKET equal to the size of a pointer. You can still use comparisons with -1 for error, though Microsoft has a macro called INVALID_SOCKET to hide this.

  • For things like setting non-blocking flags, you'll use ioctlsocket() instead of fcntl().

  • You'll have to use send() and recv() instead of write() and read().

As for whether or not you will lose portability with Linux code if you start coding for Winsock... If you are not careful, then yes. But you can write code that tries to bridge the gaps using #ifdefs..

For example:

#ifdef _WINDOWS

/* Headers for Windows */
#include <winsock2.h>
#include <windows.h>

#else

/* Headers for POSIX */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

/* Mimic some of the Windows functions and types with the
 * POSIX ones.  This is just an illustrative example; maybe
 * it'd be more elegant to do it some other way, like with
 * a proper abstraction for the non-portable parts. */

typedef int SOCKET;

#define INVALID_SOCKET  ((SOCKET)-1)

/* OK, "inline" is a C99 feature, not C89, but you get the idea... */
static inline int closesocket(int fd) { return close(fd); }
#endif

Then once you do something like this, you can code against the functions which appear in both OS's, using these wrappers where appropriate.

asveikau
Does this mean that I won't have portability to Linux? Is the API totally different than the Linux way?
Rosarch
@Rosarch I've updated my answer to reflect some of your questions.
asveikau
You'll probably benefit from thesehttp://tangentsoft.net/wskfaq/articles/lame-list.htmlhttp://beej.us/guide/bgnet/
Arthur Kalliokoski
Rather than littering your code with #ifdefs, you could instead simply wrap WinSock with functions that give it a halfway-POSIX-compatible interface...
R..
@R.. - Well, this is pretty much what I was trying to illustrate, however with the ifdef can be confined to a header. I don't consider having a single ifdef in an out-of-the-way header to be "litter", but at any rate my answer was meant to illustrate the differences and how one might bridge them, not necessarily meant to provide a final implementation and final stylistic choices.
asveikau