SO_REUSEADDR and windows enhanced socket security

yesin v.yesin@gmail.com
Tue Dec 15 15:49:00 GMT 2009


looks like a problem with SO_REUSEADDR exists in CYGWIN for all windows 
with support for "Enhanced socket security" (see 
http://msdn.microsoft.com/en-us/library/ms740621(VS.85).aspx 
<http://www.google.com/url?sa=D&q=http://msdn.microsoft.com/en-us/library/ms740621%28VS.85%29.aspx&usg=AFQjCNF9bXOmPTwYjiP37Xdq2xRAYNXfWg>) 


i'am trying to start multimple simultaneous UDP listeners for a 
multicast packets on a single machine (reuse same address and port with 
SO_REUSEADDR)

i've done such tests with cygwin 1.7 beta in windows vista, server 2008, 
7 environment - all with no success, i.e. i can't start more than one 
listener (i see an error message Address already in use in bind())!
in windows xp all works as expected!

i'll show some samples to demonstrate this:
=================listener.c========================
#include <sys/types.h>
#ifndef __MINGW32__
        #include <sys/socket.h>
        #include <arpa/inet.h>
        #include <netinet/in.h>
#else
        #include <winsock2.h>
        #include <ws2tcpip.h>
#endif
#include <stdio.h>
#include <stdlib.h>
struct sockaddr_in localSock;
struct ip_mreq group;
int sd;
int datalen;
char databuf[1024];
int main(int argc, char *argv[])
{
        struct sockaddr_in sender_addr;
        int sender_addr_size = sizeof(sender_addr);
#ifdef __MINGW32__
        WSADATA wsadata;
        if (WSAStartup(MAKEWORD(2,2), &wsadata) == SOCKET_ERROR) {
                printf("can't WSAStartup\n");
                exit(1);
        }
#endif
        /* Create a datagram socket on which to receive. */
        sd = socket(AF_INET, SOCK_DGRAM, 0);
        if(sd < 0)
        {
                printf("Opening datagram socket error %d\n", sd);
                exit(1);
        }
        printf("Opening datagram socket....OK.\n");
        /* Enable SO_REUSEADDR to allow multiple instances of this */
        /* application to receive copies of the multicast datagrams. */
        {
                int reuse = 1;
                if(setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char 
*)&reuse, sizeof
(reuse)) < 0)
                {
                        perror("Setting SO_REUSEADDR error");
                        close(sd);
                        exit(1);
                }
                printf("Setting SO_REUSEADDR...OK.\n");
        }
        /* Bind to the proper port number with the IP address */
        /* specified as INADDR_ANY. */
        memset((char *) &localSock, 0, sizeof(localSock));
        localSock.sin_family = AF_INET;
        localSock.sin_port = htons(4321);
        localSock.sin_addr.s_addr = INADDR_ANY;
        if(bind(sd, (struct sockaddr*)&localSock, sizeof(localSock)))
        {
                perror("Binding datagram socket error");
                close(sd);
                exit(1);
        }
        printf("Binding datagram socket...OK.\n");
        /* Join the multicast group 226.1.1.1 on the local 203.106.93.94 */
        /* interface. Note that this IP_ADD_MEMBERSHIP option must be */
        /* called for each local interface over which the multicast */
        /* datagrams are to be received. */
        group.imr_multiaddr.s_addr = inet_addr("226.1.1.1");
        group.imr_interface.s_addr = 
INADDR_ANY;//inet_addr("203.106.93.94");
        if(setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group,
sizeof(group)) < 0)
        {
                perror("Adding multicast group error");
                close(sd);
                exit(1);
        }
        printf("Adding multicast group...OK.\n");
        /* Read from the socket. */
        datalen = sizeof(databuf);
        while(1)
        {
                printf("Receiving...\n");
                if(recvfrom(sd, databuf, datalen, 0, (struct sockaddr *)
&sender_addr, &sender_addr_size) < 0)
                {
                        perror("Reading datagram message error");
                        close(sd);
                        exit(1);
                }
                else
                {
                        printf("Reading datagram message...OK.\n");
                        printf("The message from multicast server is: 
\"%s\"\n", databuf);
                }
        }
        return 0;
}

===============================================================
============send.c==============================================
/* Send Multicast Datagram code example. */
#include <sys/types.h>
#ifndef __MINGW32__
        #include <sys/socket.h>
        #include <arpa/inet.h>
        #include <netinet/in.h>
#else
        #include <winsock2.h>
        #include <ws2tcpip.h>
#endif
#include <stdio.h>
#include <stdlib.h>
struct in_addr localInterface;
struct sockaddr_in groupSock;
int sd;
char databuf[1024] = "Multicast test message!";
int datalen = sizeof(databuf);
int main (int argc, char *argv[ ])
{
#ifdef __MINGW32__
        WSADATA wsadata;
        if (WSAStartup(MAKEWORD(2,2), &wsadata) == SOCKET_ERROR) {
                printf("can't WSAStartup\n");
                exit(1);
        }
#endif
        /* Create a datagram socket on which to send. */
        sd = socket(AF_INET, SOCK_DGRAM, 0);
        if(sd < 0)
        {
                perror("Opening datagram socket error");
                exit(1);
        }
        printf("Opening the datagram socket...OK.\n");
        /* Initialize the group sockaddr structure with a */
        /* group address of 225.1.1.1 and port 5555. */
        memset((char *) &groupSock, 0, sizeof(groupSock));
        groupSock.sin_family = AF_INET;
        groupSock.sin_addr.s_addr = inet_addr("226.1.1.1");
        groupSock.sin_port = htons(4321);
        /* Disable loopback so you do not receive your own datagrams.
        {
                char loopch = 0;
                if(setsockopt(sd, IPPROTO_IP, IP_MULTICAST_LOOP, (char 
*)&loopch,
sizeof(loopch)) < 0)
                {
                        perror("Setting IP_MULTICAST_LOOP error");
                        close(sd);
                        exit(1);
                }
                printf("Disabling the loopback...OK.\n");
        }
        */
        /* Set local interface for outbound multicast datagrams. */
        /* The IP address specified must be associated with a local, */
        /* multicast capable interface. */
        localInterface.s_addr = INADDR_ANY;
        if(setsockopt(sd, IPPROTO_IP, IP_MULTICAST_IF, (char *)
&localInterface, sizeof(localInterface)) < 0)
        {
                perror("Setting local interface error");
                exit(1);
        }
        printf("Setting the local interface...OK\n");
        /* Send a message to the multicast group specified by the*/
        /* groupSock sockaddr structure. */
        /*int datalen = 1024;*/
        if(sendto(sd, databuf, datalen, 0, (struct sockaddr*)&groupSock,
sizeof(groupSock)) < 0)
        {
                perror("Sending datagram message error");
                exit(1);
        }
        printf("Sending datagram message...OK\n");
#ifdef __MINGW32__
        closesocket(sd);
        WSACleanup();
#endif
        return 0;
}

===============================================================
with cygwin environment i can't run multiple listerers... bind error:
Address already in use!
(
building with cygwin:
gcc -o listener.cygwin.exe listener.c
gcc -o send.cygwin.exe send.c
)
but with mingw all works as expected!
(
building with mingw:
gcc -o listener.mingw.exe listener.c -lws2_32
gcc -o send.mingw.exe send.c -lws2_32
or in mingw environment:
gcc -mno-cygwin -o listener.mingw.exe listener.c -lws2_32
gcc -mno-cygwin -o send.mingw.exe send.c -lws2_32
)

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple



More information about the Cygwin mailing list