posix style DGRAM sockets with cygwin.dll

Robert A. Mackie robert_mackie@mail.com
Mon Aug 23 23:39:00 GMT 1999


I'm trying to get a very simple UDP example ported to cygwin as a
starting point for some real code I expect to develop.  Everything
compiles and links, but the sockets don't communicate.  When built for
unix the same code works fine.  (unless I've introduced some small bug
trying to get it to work under cygwin.)  I notice I'm not the first to
say something like this.  The last person was using the -no-cygwin
option and was told to call WSAStartup.  I read as much documentation as
I could find.  It looked to me like that was not necessary when using
the posix calls, rather than the winsock calls.  (Maybe I'm wrong ?)

If I do need to initialize winsock explicitly, could you help me with a
couple of details? The only place that I see WSAStartup and WSACleanup
defined is in <Windows32/Sockets.h>.  This file seems to be set up for
an MSC compiler, and includes a bunch of other similar headers.  When I
include any of them and the standard headers I'm used to, I get all
sorts of re-definition collisions between the headers.  When I include
them without the standard headers, things like strerror aren't defined.

The specific problem I'm having is that the datagrams never get through
to the receiver.  I have an alternate client and server that I tossed
together in Java to make sure my system was working (DNS et al.), and
while they work, they show me that neither the client nor the server
developed using cygwin appear to actually use the network.  For example,
I can bind the Java server to port 7000, and then launch the server
developed under cygwin on port 7000, and it doesn't complain.

Clearly, I'm missing something fundamental.  Thanks for any help you can
provide.

Rob Mackie.

Here is the code; it's a dirty adaption of code found in Stephen's book
on network programming:

server.cc:
#include "DataGramUtility.hh"

int main(int c, char* argv[])
{
 return DataGramUtility::server(c, argv);
}

client.cc:
#include "DataGramUtility.hh"

int main(int c, char* argv[])
{
 return DataGramUtility::client(c, argv);
}

DataGramUtility.hh:
#if( ! defined(DATA_GRAM_UTILITY) )
#define DATA_GRAM_UTILITY

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

class DataGramUtility
{

public:
 static
 int client(int argc, char* argv[]);

 static
 int server(int argc, char* argv[]);


private:

 static
 int initialize();

 static
 int cleanup();


 static
 int serverLoop(
       int sockfd
  , struct sockaddr* pcli_addr
  , int maxclilen);

 static
 int clientLoop( FILE* fp
  , int sockfd
  , struct sockaddr* pserv_addr
  , int servlen);

};

DataGramUtility.cc:

#include "DataGramUtility.hh"

#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <errno.h>

#define MAXMESG 2048

#define LOCATION __FILE__, __LINE__
void printError(const char* file, int line)
{
 printf("%s:%d - %s\n"
  , file, line, strerror( errno ));
}

int
DataGramUtility::serverLoop(int sockfd
 , struct sockaddr* pcli_addr
 , int maxClientLength)
{
 int byteCount;
 int clientLength;
 char message[MAXMESG];

 while( true )
 {
  clientLength = maxClientLength;
  printf("waiting to recieve\n");
  byteCount
   = recvfrom(sockfd, message, MAXMESG, 0, pcli_addr, &clientLength);
  if( byteCount < 0 )
  {
   printf("DataGramUtility::serverLoop - recvfrom error: %d\n"
    , byteCount);
   printError(LOCATION);
  }
  message[byteCount] = '\0';
  printf("received: %s\n", message);
  if( sendto(
      sockfd
    , message
    , byteCount
    , 0, pcli_addr, clientLength) != byteCount)
  {
   printf("DataGramUtility::serverLoop - sendto error\n");
   printError(LOCATION);
  }
  printf("echo'd back to sender\n");
 }
 return 0;
}


#define MAXLINE 512

int
DataGramUtility::clientLoop(
   FILE* fp
 , int sockfd
 , struct sockaddr* pserv_addr
 , int serverLength)
{
 int byteCount;
 char sendline[MAXLINE];
 // char recvline[MAXLINE+1];

 printf("Ready to send\n");
 while( fgets(sendline, MAXLINE, fp) != NULL )
 {
  printf("read: %s\n", sendline);
  byteCount = strlen(sendline);
  if( sendto(
    sockfd
    , sendline
    , byteCount
    , 0, pserv_addr, serverLength) != byteCount)
  {
   printf("DataGramUtility::client - sendto error on socket\n");
   printError(LOCATION);
  }
  printf("sent\n");
#if 0
  byteCount = recvfrom(sockfd
   , recvline
   , MAXLINE
   , 0
   , (struct sockaddr*)0
   , (int*) 0 );

  if( byteCount < 0 )
  {
   printf("DataGramUtility::client - recvfrom error on socket\n");
   printError(LOCATION);
  }
  printf("received\n");
  recvline[byteCount] = 0;
  fputs(recvline, stdout);
#endif
 }
 return 0;
}


int DataGramUtility::client(int argc, char* argv[])
{
 if(DataGramUtility::initialize() == -1)
 {
  printf("Couldn't initialize winsock\n");
  return -1;
 }
 int sockfd;
 struct sockaddr_in client_address;
 struct sockaddr_in server_address;

 if( argc < 3 )
 {
  printf("Usage: %s hostip port\n", argv[0]);
  return -1;
 }

 const char* SERVER_HOST_ADDRESS = argv[1];
 const int SERVER_UDP_PORT = atoi(argv[2]);

 bzero((char*)&server_address, sizeof(server_address));
 server_address.sin_family      = AF_INET;
 server_address.sin_addr.s_addr = inet_addr(SERVER_HOST_ADDRESS);
 server_address.sin_port        = htonl(SERVER_UDP_PORT);

 if( server_address.sin_addr.s_addr == htonl(0x7F000001) )
 {
  printf("Address is local host.\n");
 }

 printf("IP: ");
 for( int i = 0; i<4; i++ )
 {
  printf( "%d.", ((unsigned char*)(&server_address.sin_addr.s_addr))[i]
);
 }

 if( (sockfd = socket(AF_INET, SOCK_DGRAM, 0 )) < 0 )
 {
  printf("DataGramUtility::client - can't open datagram socket\n");
  printError(LOCATION);
  return -1;
 }

 bzero((char*)&client_address, sizeof(client_address));
 client_address.sin_family      = AF_INET;
 client_address.sin_addr.s_addr = htonl(INADDR_ANY);
 client_address.sin_port        = htonl(0);

 if( bind(
    sockfd
  , (struct sockaddr*)&client_address
  , sizeof(client_address)) < 0 )
  {
   printf("DataGramUtility::client - can't bind local address\n");
   printError(LOCATION);
   return -1;
  }

 DataGramUtility::clientLoop(
    stdin
  , sockfd
  , (struct sockaddr*)&server_address
  , sizeof(server_address));

 close(sockfd);
 DataGramUtility::cleanup();
 return 0;
}

int DataGramUtility::server(int argc, char* argv[])
{
 if(DataGramUtility::initialize() == -1)
 {
  printf("Couldn't initialize winsock\n");
  return -1;
 }
 int sockfd;
 struct sockaddr_in server_address;
 struct sockaddr_in client_address;

 if( argc < 2 )
 {
  printf("Usage: %s port\n", argv[0]);
  return -1;
 }

 const int SERVER_UDP_PORT = atoi(argv[1]);

 if( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 )
 {
  printf("DataGramUtility::server - can't open datagram socket\n");
  printError(LOCATION);
  return -1;
 }

 bzero((char*)&server_address, sizeof(server_address));
 server_address.sin_family      = AF_INET;
 server_address.sin_addr.s_addr = htonl(INADDR_ANY);
 server_address.sin_port        = htonl(SERVER_UDP_PORT);

 if( bind(
       sockfd
  , (struct sockaddr*) &server_address
  , sizeof(server_address)) < 0 )
 {
  printf("DataGramUtility::server - can't bind local address\n");
  printError(LOCATION);
  return -1;
 }

 DataGramUtility::serverLoop(
    sockfd
  , (struct sockaddr*)&client_address
  , sizeof(client_address));

 DataGramUtility::cleanup();
 return 0;
}


int
DataGramUtility::initialize()
{
#if 0
 WSADATA WSAData;
 if (WSAStartup(0x0101, &WSAData)) {
  printf("WSAStartup failed (%d)\n",WSAGetLastError());
  return -1;
 }
#endif
 return 0;
}

int
DataGramUtility::cleanup()
{
#if 0
 WSACleanup();
#endif
}


More information about the Cygwin mailing list