Reputation: 13
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
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
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