如何使用 SOCK_DGRAM 制作双向 unix 域套接字?

Posted

技术标签:

【中文标题】如何使用 SOCK_DGRAM 制作双向 unix 域套接字?【英文标题】:How to make two-directional unix domain sockets with SOCK_DGRAM? 【发布时间】:2011-09-06 20:02:19 【问题描述】:

我正在尝试编写一个简单的 Unix 数据报服务器/客户端,但遇到了一些问题。我想要的是一个服务器,它在数据报套接字上侦听并向原始发送者发送对收到的每条消息的回复。我决定先尝试使用socat 作为“服务器”并用C 编写客户端。我正在像这样运行socat:

socat UNIX-DGRAM:/tmp/test.socket,fork EXEC:echo

据我所知,这应该收听/tmp/test.socket 并回复使用相同字符串收到的所有内容?然后我有一个看起来像这样的客户端程序(为了清楚起见,删除了错误检查):

int s = socket(AF_UNIX, SOCK_DGRAM, 0);
struct sockaddr_un sa;
sa.sun_family = AF_UNIX;
strcpy(sa.sun_path, "/tmp/test.socket");

const char *data = "Testing data";
int err = sendto(s, data, strlen(data), 0, (struct sockaddr *)(&sa), sizeof(struct sockaddr_un));

printf("Sent!\n");

unsigned char *buffer = malloc(BUFFER_LENGTH);
struct sockaddr_storage recv_sa;
int recv_sa_len = 0;
int recv_len = recvfrom(s, buffer, BUFFER_LENGTH, 0, (struct sockaddr *)&recv_sa, &recv_sa_len);

for (int i = 0; i < recv_len; i++) 
    putc(buffer[i], stdout);

printf("\n");

它应该发送数据包(有效),接收数据包,然后将其打印出来,但程序似乎无法接收数据包。我在这里做错了什么,还是我对 Unix 套接字有根本的误解?谢谢!

【问题讨论】:

【参考方案1】:

查看 Michael Kerrisk 的客户端/服务器程序(client、server)的 AF_UNIX SOCK_DGRAM 示例,该示例发表在他的《Linux 编程接口》第 57 章中。

【讨论】:

我不认为原始参考是有效的答案。【参考方案2】:

套接字需要有地址才能接收数据包。您可以使用基于 PID 的唯一套接字文件名调用 bind(),或者在 linux 中使用自动绑定抽象地址,如果在 send 之前调用:

bind(s, (const struct sockaddr *)&sa, sizeof(sa_family_t));

【讨论】:

【参考方案3】:

在尝试向回显服务器发送任何内容之前,您应该调用 connect

看看:http://beej.us/guide/bgipc/output/html/multipage/unixsock.html

【讨论】:

是这样的,因为我使用的是数据报套接字(不是 SOCK_STREAM),它的功能应该类似于 UDP,我可以在我喜欢的任何地方发送数据报而无需先连接?就像我提到的,客户端发送到服务器的部分确实有效。谢谢! 明明是数据报,但你建议连接。有什么原因吗?

以上是关于如何使用 SOCK_DGRAM 制作双向 unix 域套接字?的主要内容,如果未能解决你的问题,请参考以下文章

SOCK_DGRAM 和 SOCK_STREAM 在上下文 AF_UNIX 套接字中的用途是啥?

点图语言 - 如何自动制作双向边?

创建双向管道或任何类似行为的 Unix 方式?

为啥套接字(AF_INET、SOCK_DGRAM、IPPROTO_UDP)会失败?

C++ 使用 send_to 提升 unix 域套接字

unison+inotify实现数据实时双向同步