Unix域套接字:在一个服务器进程和几个客户进程之间使用数据报通信

前端之家收集整理的这篇文章主要介绍了Unix域套接字:在一个服务器进程和几个客户进程之间使用数据报通信前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我想在Linux上的几个进程之间建立一个IPC连接。我从来没有使用UNIX套接字,因此我不知道这是否是这个问题的正确方法

一个进程接收数据(未格式化,二进制),并将使用数据报协议(即类似于具有AF_INET的UDP)通过本地AF_UNIX套接字分发这些数据。从此进程发送到本地Unix套接字的数据应由在同一套接字上监听的多个客户端接收。接收器的数量可以变化。

为了实现这一点,下面的代码用于创建套接字并向其发送数据(服务器进程):

struct sockaddr_un ipcFile;
memset(&ipcFile,sizeof(ipcFile));
ipcFile.sun_family = AF_UNIX;
strcpy(ipcFile.sun_path,filename.c_str());

int socket = socket(AF_UNIX,SOCK_DGRAM,0);
bind(socket,(struct sockaddr *) &ipcFile,sizeof(ipcFile));
...
// buf contains the data,buflen contains the number of bytes
int bytes = write(socket,buf,buflen);
...
close(socket);
unlink(ipcFile.sun_path);

此写入返回-1,并使用errno报告ENOTCONN(“传输端点未连接”)。我想这是因为没有接收进程当前正在侦听这个本地socket,正确吗?

然后,我试图创建一个客户端连接到这个套接字。

struct sockaddr_un ipcFile;
memset(&ipcFile,sizeof(ipcFile));
...
char buf[1024];
int bytes = read(socket,sizeof(buf));
...
close(socket);

这里,绑定失败(“地址已在使用中”)。那么,我需要设置一些套接字选项,还是这通常是错误方法

感谢您的任何意见/解决方案!

有一个技巧使用unix数据报套接字。与流套接字(tcp或unix域)不同,数据报套接字需要为服务器和客户端定义端点。当在流套接字中建立连接时,操作系统隐式地创建客户端的端点。无论这对应于临时TCP / UDP端口还是对于unix域的临时inode,将为您创建客户端的端点。这就是为什么你通常不需要发出bind()对客户端中的流套接字的调用

您看到“地址已在使用”的原因是因为您要告诉客户端绑定到与服务器相同的地址。 bind()关于断言外部标识。两个套接字通常不能具有相同的名称

使用数据报套接字,特别是unix域数据报套接字,客户端必须bind()到其自己的端点,然后connect()到服务器的端点。这里是你的客户端代码,稍作修改,引入一些其他好东西:

char * server_filename = "/tmp/socket-server";
char * client_filename = "/tmp/socket-client";

struct sockaddr_un server_addr;
struct sockaddr_un client_addr;
memset(&server_addr,sizeof(server_addr));
server_addr.sun_family = AF_UNIX;
strncpy(server_addr.sun_path,server_filename,104); // XXX: should be limited to about 104 characters,system dependent

memset(&client_addr,sizeof(client_addr));
client_addr.sun_family = AF_UNIX;
strncpy(client_addr.sun_path,client_filename,104);

// get socket
int sockfd = socket(AF_UNIX,0);

// bind client to client_filename
bind(sockfd,(struct sockaddr *) &client_addr,sizeof(client_addr));

// connect client to server_filename
connect(sockfd,(struct sockaddr *) &server_addr,sizeof(server_addr));

...
char buf[1024];
int bytes = read(sockfd,sizeof(buf));
...
close(sockfd);

在这一点上,您的套接字应该完全设置。我认为理论上你可以使用read()/ write(),但通常我会使用send()/ recv()数据报套接字。

通常你会想在每个这些调用后检查错误,然后发出perror()。它会大大帮助你,当事情出了问题。一般来说,使用这样的模式:

if ((sockfd = socket(AF_UNIX,0)) < 0) {
    perror("socket Failed");
}

这几乎任何C系统调用

最好的参考是Steven的“Unix网络编程”。在第三版中,第15.4节,第415-419页显示了一些例子并列出了许多注意事项。

顺便说一下,参考

I guess this is because no receiving process is currently listening to this local socket,correct?

我想你是正确的ENOTCONN错误从write()在服务器。 UDP套接字通常不会抱怨,因为它没有设备知道客户端进程是否正在侦听。但是,unix域数据报套接字不同。实际上,如果客户端的接收缓冲区已满,write()将实际阻塞,而不是丢弃数据包。这使得unix域数据报套接字比IPC的IPC优越得多,因为UDP在负载下,甚至在localhost上肯定会丢弃数据包。另一方面,这意味着你必须小心快速的作家和慢读者。

原文链接:https://www.f2er.com/bash/389318.html

猜你在找的Bash相关文章