LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   Reuse socket fails "Address already in use" or "Connection refused" (http://www.linuxquestions.org/questions/programming-9/reuse-socket-fails-address-already-in-use-or-connection-refused-807813/)

dec10 05-14-2010 08:24 AM

Reuse socket fails "Address already in use" or "Connection refused"
 
Problem: can't restart programs which use socket to communicate.

Symptom: Restart Listener dies "Address already in use".
Restart Caller dies "connection refused"

System: Ubuntu 10 (and 9)

General description.
Run Listener and Caller - ok. Stop Caller. Can rerun.
Stop Listener. Now neither will run, errors as above.

Tried?:-
Much net search, but most of it old, and doesn't fix.
BOTH programs try setsockopt with SO_REUSEADDR, to no avail.

Of note:
They are using AF_UNIX. (much of the net stuff is for reuse of ports on AF_INET.

I'm sure it's too blatant to be anything but a problem with this newbie, but any help would be appreciated - I'm stuck. (I wish "connection refused" would say why!)

Thanks

Minimised code below:-

Listener:-
Code:

        struct sockaddr_un sockaddr ;
        int sd;
        int turniton;
        char wait;

        if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
                printf("Can't get socket\n");

        turniton = 1;
        if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &turniton, sizeof(turniton)) < 0)
                printf("can't set reuse - %s\n", strerror(errno));

        memset(&sockaddr, '\0', sizeof(sockaddr)) ;
        sockaddr.sun_family = AF_UNIX ;
        strcpy(sockaddr.sun_path, "/var/ipcf/ipcfc") ;

        if (bind(sd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) == -1)
                printf("bind failed - %s\n", strerror(errno)) ;

        wait = getchar();

        close(sd);

----------------------

Caller

Code:

        struct sockaddr_un        sockaddr ;
        int                        sd ;
        int                        turniton;

        sd = socket(AF_UNIX, SOCK_STREAM, 0) ;
        if (!sd)
                printf("no sd!\n");

        turniton = 1;
        if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &turniton, sizeof(turniton)) < 0)
                printf( "Can't set reuse - %s\n", strerror(errno));

        memset(&sockaddr, '\0', sizeof(sockaddr)) ;
        sockaddr.sun_family = AF_UNIX ;
        strcpy(sockaddr.sun_path, "/var/ipcf/ipcfc") ;

        if (connect(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) == -1)
                printf("connect failed - %s\n", strerror(errno));

        close(sd);


ForzaItalia2006 05-15-2010 10:39 AM

Hey,

first of all welcome to the linux forum :-)

You geht this 'address alrady in use' because the path name, in your case /var/ipcf/ipcfc, still exists when your program exists. When you then try to re-bind to this existing path, you get the error message, though you need to make sure that the file system path does not exist when you bind to it, e.g. by calling unlink(2)

Why the re-use doesn't work, I don't really know, yet ;-)

- Andi -

dec10 05-15-2010 12:34 PM

Yes, thanks Andi.
For now I have got round it by sharing an incremental new name on startup.
This has the spinoff that the caller can even start before the listener and wait after "connection refused", because it can tell when the new listener is available.
So...
Problem bypassed with additional benefits.
Problem is still there and I would like to understand the proper cure, because surely I'm not the first to fall over this.

dec10 05-15-2010 01:14 PM

Ha!
A single keyword in your answer is the key.
Immediately before Bind, call unlink(name) and ignore any error. This should mean the file is not there or is no longer there.

So I now have both bits in there, and no problems.

Thanks!

[ Still think the original problem is valid if anyone reads this far ]


All times are GMT -5. The time now is 01:37 AM.