linux – Unix域套接字:accept()没有设置sun_path
|
我正在使用Unix域套接字进行一些测试,我可以毫无问题地通过它们进行通信,但是,当我在测试程序的服务器端调用accept()时,返回的struct sockaddr_un不包含sun_path. 我很确定Inet套接字在accept()调用之后正确地填写了地址和端口,所以我在测试程序中做错了什么,或者我期待错误的结果? 我正在运行CentOS 6.2和gcc 4.4.6. 示例代码: server.c #include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define NAME "socket"
int main(int argc,char **argv)
{
int sock,msgsock,rval;
struct sockaddr_un server,client;
char buf[1024];
sock = socket(AF_UNIX,SOCK_STREAM,0);
if (sock < 0) {
perror("opening stream socket");
exit(1);
}
server.sun_family = AF_UNIX;
strcpy(server.sun_path,NAME);
if (bind(sock,(struct sockaddr *) &server,sizeof(struct sockaddr_un))) {
perror("binding stream socket");
exit(1);
}
printf("Socket has name %sn",server.sun_path);
listen(sock,5);
for (;;) {
socklen_t len = sizeof(client);
msgsock = accept(sock,(struct sockaddr *)&client,&len);
if (msgsock == -1)
perror("accept");
else do {
printf("strlen(sun_path) = %zun",strlen(client.sun_path));
bzero(buf,sizeof(buf));
if ((rval = read(msgsock,buf,1024)) < 0)
perror("reading stream message");
else if (rval == 0)
printf("Ending connectionn");
else
printf("-->%sn",buf);
} while (rval > 0);
close(msgsock);
}
close(sock);
unlink(NAME);
return 0;
}
client.c #include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define DATA "Half a league,half a league . . ."
int main(int argc,char **argv)
{
int sock;
struct sockaddr_un server;
if (argc < 2) {
printf("usage:%s <pathname>",argv[0]);
exit(1);
}
sock = socket(AF_UNIX,argv[1]);
if (connect(sock,sizeof(struct sockaddr_un)) < 0) {
close(sock);
perror("connecting stream socket");
exit(1);
}
if (write(sock,DATA,sizeof(DATA)) < 0)
perror("writing on stream socket");
close(sock);
return 0;
}
只是重申一下这个问题: 为什么在服务器上的accept()调用之后没有填写sun_path? 解决方法我真的不确定这是否是一个答案.可能它更像是关于某些研究的思考,尽管在阅读时可能仍然值得.至少在Linux 3.16.0,NetBSD 6.1.4和Darwin 13.1.0内核中,accept(2)填充的值似乎与协议无关.在实践中,这意味着接受(2),struct sockaddr *的第??二个参数仅被填充到所有协议之间共享的内容.因此,在成功接受(2)后你手中的东西远不是一个完整的结构sockaddr_un. 可能没有人认为在接受(2)的第一次实现完成时它会非常重要,现在我们仍然坚持这一点.幸运的是,有一种解决方法,如果有人丢失了用于socket的路径名并调用bind(2),现在又想找到它. 使用struct sockaddr_storage和getsockname(2),可以访问成员sun_path.因此,为了确保获得所有有用的细节,请在成功调用accept(2)之后调用getsockname(2)(这将在您的server.c中的第40行之后放置): struct sockaddr_storage ss;
socklen_t sslen = sizeof(struct sockaddr_storage);
if (getsockname(msgsock,(struct sockaddr *)&ss,&sslen) == 0) {
struct sockaddr_un *un = (struct sockaddr_un *)&ss;
printf("socket name is: %sn",un->sun_path);
}
或者只是使用这个: #include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define NAME "socket"
int main(int argc,strlen(client.sun_path));
struct sockaddr_storage ss;
socklen_t sslen = sizeof(struct sockaddr_storage);
if (getsockname(msgsock,&sslen) == 0) {
struct sockaddr_un *un = (struct sockaddr_un *)&ss;
printf("socket name is: %sn",un->sun_path);
}
bzero(buf,buf);
} while (rval > 0);
close(msgsock);
}
close(sock);
unlink(NAME);
return 0;
}
这已经过测试,即.它编译并产生预期的结果,用于运行内核3.16.0的GNU / Linux系统,运行6.1.4内核的NetBSD系统,以及运行13.1.0内核的OS / X Mavericks系统.在所有这些接受(2)的行为是一致的:sun_path在填充的结构中找不到. getsockname(2)的行为在不同的操作环境之间也是一致的,使所有协议特定的细节都可用. (编辑:清远站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |

