user3605146
user3605146

Reputation: 13

datagram sockets in c. looks like parent process never binds

i have tried to execute the following code of two processes. the child sends a datagram and the parent is supposed to receive it and print it . The parent process looks like it does not bind (error: address already in use). any ideas?

#include <sys/socket.h>
#include <sys/un.h>
#include <signal.h>
#include <stdio.h>

#define N 9

int main(int argc, char *argv[]) {

int pid,s,n,addrlen; 
char msg[N]; 
struct sockaddr_un addr;

addr.sun_family=AF_UNIX;        
strcpy(addr.sun_path,"test-socket");    // pathname
addrlen=sizeof(addr.sun_family)+strlen(addr.sun_path);

if (!(pid=fork())) {
    printf("child\n");
    s=socket(PF_UNIX,SOCK_DGRAM,0); 
    sleep(3); /* wait for parent to bind */

    sendto(s,"hi parent",9,0,(struct sockaddr*)&addr,addrlen);  
    printf("child sent\n");
    close(s);

    return(0);
}
printf("father\n");
s=socket(PF_UNIX,SOCK_DGRAM,0);
bind(s,(struct sockaddr *)&addr,addrlen);   // error here

n=recvfrom(s,msg,N,0,NULL,NULL);        
if(n<=0){printf("error\n");}
msg[n]='\0'; printf("%s\n",msg);
close(s);
unlink("test-socket");              

return(0);

}

Upvotes: 1

Views: 106

Answers (2)

matt
matt

Reputation: 79773

On my system (Mac OS X Snow Leopard) sockaddr_un looks like this:

struct  sockaddr_un {
        unsigned char   sun_len;        /* sockaddr len including null */
        sa_family_t     sun_family;     /* [XSI] AF_UNIX */
        char            sun_path[104];  /* [XSI] path name (gag) */
};

Assuming yours looks something similar, your calculation of addrlen (sizeof(addr.sun_family)+strlen(addr.sun_path)) is wrong, which will result in calls that use it sendto and bind using a different path than the one you think you are using – it will be truncated.

Your call to bind is probably creating a socket file named something like test-socke (note the missing t at the end). When your program finishes it tries to unlink the non-existing file test-socket. This means that the next time you run the program the file you are trying to bind to (test-socke) already exists, and so bind will fail in the way you are seeing.

To fix this you need to make sure you are using the correct length for addrlen. The simplest and safest way is probably to use sizeof(addr):

addrlen = sizeoff(addr);

You could also use SUN_LEN if it is available, which might save you copying a few bytes if that concerns you:

addrlen = SUN_LEN(&addr);

If you want to calculate the correct length yourself (e.g. SUN_LEN isn’t availble) then try this:

addrlen = sizeof(addr) - sizeof(addr.sun_path) + strlen(addr.sun_path);

(This is adapted from the definition of SUN_LEN on my system.)

Upvotes: 0

Sasikanth Bharadwaj
Sasikanth Bharadwaj

Reputation: 1457

Why don't you bind before fork? Waiting for a fixed amount of time and then sending data is not a good idea

Upvotes: 1

Related Questions