我试图执行以下两个进程的代码。 孩子发送数据报,父母应该接收并打印它 。父进程看起来好像没有绑定(错误:地址已在使用中)。 任何想法?
#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);
}
答案 0 :(得分:1)
为什么不在fork之前绑定?等待一段固定的时间然后发送数据不是一个好主意
答案 1 :(得分:0)
在我的系统上(Mac OS X Snow Leopard)sockaddr_un
看起来像这样:
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) */
};
假设您的内容类似,那么您对addrlen
(sizeof(addr.sun_family)+strlen(addr.sun_path)
)的计算是错误的,这会导致使用sendto
和bind
的调用使用不同的路径比你认为你使用的那个 - 它将被截断。
您对bind
的调用可能正在创建一个名为test-socke
的套接字文件(请注意最后丢失的t
)。程序完成后,尝试unlink
不存在的文件test-socket
。这意味着下次运行程序时,您尝试bind
到(test-socke
)的文件已经存在,因此bind
将以您看到的方式失败。
要解决此问题,您需要确保使用addrlen
的正确长度。最简单和最安全的方法可能是使用sizeof(addr)
:
addrlen = sizeoff(addr);
如果它可用,你也可以使用SUN_LEN
,如果你担心的话可能会节省你复制几个字节:
addrlen = SUN_LEN(&addr);
如果您想自己计算正确的长度(例如SUN_LEN
不可用),请尝试以下操作:
addrlen = sizeof(addr) - sizeof(addr.sun_path) + strlen(addr.sun_path);
(这是根据我系统上SUN_LEN
的定义改编的。)