X-Recipient: archive-cygwin AT delorie DOT com X-SWARE-Spam-Status: No, hits=0.0 required=5.0 tests=AWL,BAYES_00,RCVD_IN_SORBS_WEB,SPF_PASS X-Spam-Check-By: sourceware.org Message-ID: <4B27AFEB.4030609@gmail.com> Date: Tue, 15 Dec 2009 18:48:59 +0300 From: yesin User-Agent: Thunderbird 2.0.0.23 (Windows/20090812) MIME-Version: 1.0 To: cygwin AT cygwin DOT com Subject: SO_REUSEADDR and windows enhanced socket security Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-IsSubscribed: yes Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com 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 ) 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 #ifndef __MINGW32__ #include #include #include #else #include #include #endif #include #include 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 #ifndef __MINGW32__ #include #include #include #else #include #include #endif #include #include 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