Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Cygwin can't receive UDP packet using recvfrom

  1. Sep 20, 2012 #1
    Hallo,
    I have a "listener" and "talker" program, "listener" to listen an UDP packet sent by "talker".
    Both work in linux machine (actually I test in same machine, so using localhost as address).
    I run "listener" in linux and "talker" in windows (via cygwin), it's work fine.
    However, it doesn't work in opposite, i.e. run "talker" in linux and "listener" in windows (cygwin).

    Could you help me to find out what is wrong?

    I have tried to use 0, MSG_PEEK, MSG_WAITALL in recvfrom() argument, all don't work.

    Here is the code:

    listener.c
    Code (Text):

    /*
    ** listener.c -- a datagram sockets "server" demo
    */

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <netdb.h>

    #define MYPORT "4950"   // the port users will be connecting to

    #define MAXBUFLEN 100

    // get sockaddr, IPv4 or IPv6:
    void *get_in_addr(struct sockaddr *sa)
    {
        if (sa->sa_family == AF_INET) {
            return &(((struct sockaddr_in*)sa)->sin_addr);
        }

        return &(((struct sockaddr_in6*)sa)->sin6_addr);
    }

    int main(void)
    {
        int sockfd;
        struct addrinfo hints, *servinfo, *p;
        int rv;
        int numbytes;
        struct sockaddr_storage their_addr;
        char buf[MAXBUFLEN];
        socklen_t addr_len;
        char s[INET6_ADDRSTRLEN];

        memset(&hints, 0, sizeof hints);
        hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4
        hints.ai_socktype = SOCK_DGRAM;
        hints.ai_flags = AI_PASSIVE; // use my IP

        if ((rv = getaddrinfo(NULL, MYPORT, &hints, &servinfo)) != 0) {
            fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
            return 1;
        }

        // loop through all the results and bind to the first we can
        for(p = servinfo; p != NULL; p = p->ai_next) {
            if ((sockfd = socket(p->ai_family, p->ai_socktype,
                    p->ai_protocol)) == -1) {
                perror("listener: socket");
                continue;
            }

            if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
                close(sockfd);
                perror("listener: bind");
                continue;
            }

            break;
        }

        if (p == NULL) {
            fprintf(stderr, "listener: failed to bind socket\n");
            return 2;
        }




        printf("listener: waiting to recvfrom...\n");

        addr_len = sizeof their_addr;




        if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN-1 , /*0*/MSG_PEEK,

            (struct sockaddr *)&their_addr, &addr_len)) == -1) {
            perror("recvfrom");
            exit(1);
        }

        printf("listener: got packet from %s\n",
            inet_ntop(their_addr.ss_family,
                get_in_addr((struct sockaddr *)&their_addr),
                s, sizeof s));
        printf("listener: packet is %d bytes long\n", numbytes);
        buf[numbytes] = '\0';
        printf("listener: packet contains \"%s\"\n", buf);

        close(sockfd);

        return 0;
    }
     
    talker.c
    Code (Text):

    /*
    ** talker.c -- a datagram "client" demo
    */

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <netdb.h>

    #define SERVERPORT "4950"   // the port users will be connecting to

    int main(int argc, char *argv[])
    {
        int sockfd;
        struct addrinfo hints, *servinfo, *p;
        int rv;
        int numbytes;

        if (argc != 3) {
            fprintf(stderr,"usage: talker hostname message\n");
            exit(1);
        }

        memset(&hints, 0, sizeof hints);
        hints.ai_family = AF_UNSPEC;
        hints.ai_socktype = SOCK_DGRAM;

        if ((rv = getaddrinfo(argv[1], SERVERPORT, &hints, &servinfo)) != 0) {
            fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
            return 1;
        }

        // loop through all the results and make a socket
        for(p = servinfo; p != NULL; p = p->ai_next) {
            if ((sockfd = socket(p->ai_family, p->ai_socktype,
                    p->ai_protocol)) == -1) {
                perror("talker: socket");
                continue;
            }

            break;
        }

        if (p == NULL) {
            fprintf(stderr, "talker: failed to bind socket\n");
            return 2;
        }

        if ((numbytes = sendto(sockfd, argv[2], strlen(argv[2]), 0,
                 p->ai_addr, p->ai_addrlen)) == -1) {
            perror("talker: sendto");
            exit(1);
        }

        freeaddrinfo(servinfo);

        printf("talker: sent %d bytes to %s\n", numbytes, argv[1]);
        close(sockfd);

        return 0;
    }
     
    both are the example program from http://beej.us/guide/bgnet/output/html/multipage/clientserver.html#simpleclient.
     
  2. jcsd
  3. Sep 20, 2012 #2

    jedishrfu

    Staff: Mentor

    do you have a firewall running on windows? try turning it off during your test.
     
  4. Sep 20, 2012 #3
    my Windows Firewall is off.
     
  5. Sep 20, 2012 #4

    jedishrfu

    Staff: Mentor

    can you run the listener and talker both on windows in different sessions? this would determine whether the listener can work on windows.

    is 4950 port already in use on your windows box?

    http://www.sans.org/security-resources/idfaq/oddports.php

    the website above says it could be used by icq trojan (looks like a virus maybe)

    so try using different port numbers.
     
  6. Sep 21, 2012 #5

    I like Serena

    User Avatar
    Homework Helper

    Install wireshark (http://www.wireshark.org/).

    Wireshark allows you to make a trace of all packets sent in and out.
    It comes with a nifty gui that is very intuitive.

    It's available both on Linux and Windows.
     
  7. Sep 21, 2012 #6

    chiro

    User Avatar
    Science Advisor

    Hey ksatria.

    One thing you might want to see is if you are using localhost whether there are issues about the TCP/IP stack for cygwin/windows communication regarding networking.

    To test this, you should try the following: connect to an actual IP address (not localhost) or try using two individual machines with one being a listener and another being a talker, or (if you can do this), route your packets outside of your machine and back again. A better suggestion is if you have a router, to use the router to force data to be resolved outside your own machine.

    The point of doing this is that any kind of network packet monitoring program including a firewall will pick up activity on a particular port and that means that if you get any activity, it's not the programs.

    Also try using a custom port (something with a high number) since many standard services use low ports (even as high as the thousands up to 8000 in some cases).
     
  8. Sep 21, 2012 #7
    thanks for all the responses.

    @jedishrfu
    hmm, even in same Windows, they can't communicate.
    I run "listener" in one Cygwin terminal, and run "talker" in another Cygwin terminal and issue these command:
    $ ./talker 1x.15x.7x.154 "hello cygwin"
    or by using
    $ ./talker 127.0.0.1 "hello cygwin"
    still the listener keep waiting.

    I also try to change port number to "4960" (seem nobody using), also doesn't work.

    @I like Serena
    Yes, the packet is received, I can see it from Wireshark; linux run "talker", windows (cygwin) run "listener".
    Code (Text):

    0000  6x 3x 5x 8x 4x fx 3y ey  ay 0y 1y 2y 08 00 45 00  
    0010  00 29 00 00 40 00 3e 11  ca 70 1x bx 0x 6x 1y 9y   .)..@.>. .p...g..
    0020  4y 9y bf e7 13 60 00 15  ad f0 68 65 6c 6c 6f 20   O....`.. ..hello
    0030  77 69 6e 64 6f 77 73 00  00 00 00 00               windows. ....
     
    hm, is it cygwin problem?

    @chiro
    I tried using higher port, 8666, also doesn't work, and actual IP address as well (see above).
    Using 2 machine (1 windows, 1 linux), only linux as listener and windows (cygwin) as talker that work, opposite doesn't work.


    some research in various website say there is problem with recvfrom with MGS_WAITALL, but I'm not using it.
    hmmm...... ???
     
  9. Sep 21, 2012 #8

    chiro

    User Avatar
    Science Advisor

    ksatria: can you do both a listen and talk in windows?
     
  10. Sep 21, 2012 #9
    @chiro:
    no, I can't.
    only these scenario work:
    1. linux to linux, (same machine via 127.0.0.1)
    2. windows to linux
    but not :
    1. linux to windows, nor
    2. windows to windows

    so the problem is in windows (using cygwin) side when receiving. (the code in linux and windows are exactly the same).
    from Wireshark I see the packet sent from linux machine is received in windows machine, but somehow the "listener" can't catch it.
     
  11. Sep 21, 2012 #10

    chiro

    User Avatar
    Science Advisor

    Sounds like some kind of Winsock issue.

    Have you tried using a platform specific ifdefs to load the Winsock library and then use the standard commands but calling them through the Winsock API rather than the standard?

    I'm not sure, but my guess is that all your code is wrapped around Winsock anyway for the windows implementation (which you don't see unless you dig deeper).

    So another option for you is to look at what's going on for the windows specific code and see how its configuring Winsock (since if it's configuring it wrong, then things are going to screw up).
     
  12. Sep 21, 2012 #11
    actually I'm not use winsock, I use sys/socket.h from linux, as I use cygwin.

    then, I try to make the "windows version"

    here the code, not much different

    Code (Text):

    /*
    ** listener.c -- a datagram sockets "server" demo
    */

    #include <stdio.h>
    //#include <WinSock.h>
    #include <WinSock2.h>
    #include <Windows.h>
    #include <ws2tcpip.h>


    #define MYPORT "4960"//"4950"   // the port users will be connecting to

    #define MAXBUFLEN 100

    // get sockaddr, IPv4 or IPv6:
    void *get_in_addr(struct sockaddr *sa)
    {
        if (sa->sa_family == AF_INET) {
            return &(((struct sockaddr_in*)sa)->sin_addr);
        }

        return &(((struct sockaddr_in6*)sa)->sin6_addr);
    }

    int main(void)
    {
        int sockfd;
        struct addrinfo hints, *servinfo, *p;
        int rv;
        int numbytes;
        struct sockaddr_storage their_addr;
        char buf[MAXBUFLEN];
        socklen_t addr_len;
        char s[INET6_ADDRSTRLEN];

        WSADATA wsaData;   // if this doesn't work
        //WSAData wsaData; // then try this instead

        // MAKEWORD(1,1) for Winsock 1.1, MAKEWORD(2,0) for Winsock 2.0:

        if (WSAStartup(/*MAKEWORD(1,1)*/MAKEWORD(2,0), &wsaData) != 0) {
            fprintf(stderr, "WSAStartup failed.\n");
            exit(1);
        }

        memset(&hints, 0, sizeof hints);
        hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4
        hints.ai_socktype = SOCK_DGRAM;
        hints.ai_flags = AI_PASSIVE; // use my IP

        if ((rv = getaddrinfo(NULL, MYPORT, &hints, &servinfo)) != 0) {
            fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
            return 1;
        }

        // loop through all the results and bind to the first we can
        for(p = servinfo; p != NULL; p = p->ai_next) {
            if ((sockfd = socket(p->ai_family, p->ai_socktype,
                    p->ai_protocol)) == -1) {
                perror("listener: socket");
                continue;
            }

            if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
                closesocket(sockfd);//close(sockfd);
                perror("listener: bind");
                continue;
            }

            break;
        }

        if (p == NULL) {
            fprintf(stderr, "listener: failed to bind socket\n");
            return 2;
        }




        printf("listener: waiting to recvfrom...\n");

        addr_len = sizeof their_addr;






        if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN-1 , 0,

            (struct sockaddr *)&their_addr, &addr_len)) == -1) {
            perror("recvfrom");
            exit(1);
        }

        printf("listener: got packet from %s\n",
            inet_ntop(their_addr.ss_family,
                get_in_addr((struct sockaddr *)&their_addr),
                s, sizeof s));
        printf("listener: packet is %d bytes long\n", numbytes);
        buf[numbytes] = '\0';
        printf("listener: packet contains \"%s\"\n", buf);

        closesocket(sockfd);//close(sockfd);

        return 0;
    }

     


    then I able to do Windows (winsock) to Windows (cygwin) successfully, but still can't receive from linux.
     
  13. Sep 21, 2012 #12

    chiro

    User Avatar
    Science Advisor

    One suggestion is to require a later version of WinSock: the older version 1.1 had a few problems and you'll always have 2.0 on any standard Windows OS (even 2000 and above).

    I just looked up some old code I wrote a very long time ago, and I have some comments.

    The first one is that you should make sure the socket family is set to the TCP/IP family so that it knows that you are using the UDP protocol (since you have specified SOCK_DGRAM).

    Also if you are passing a port you need to make sure you use the htons() function for servers and the htonl function as well (for setting up listening parameters).

    You need to also setup the servers and clients in a unique way: clients usually take the address as htonl(INADDR_ANY) but servers take a specific IP address in the data structure.

    The way I did it ages ago doesn't look like the way you did it, but the first thing I would do is force the family to AF_INET and also force the socket type to TCP/IP to start off with.
     
  14. Sep 21, 2012 #13

    I like Serena

    User Avatar
    Homework Helper

  15. Sep 21, 2012 #14

    chiro

    User Avatar
    Science Advisor

    Yeah, what I Like Serena said is kind of important.
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook




Similar Discussions: Cygwin can't receive UDP packet using recvfrom
  1. Cygwin + g95 (Replies: 1)

Loading...