- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我想在 Linux 上的几个进程之间建立 IPC 连接。我以前从未使用过 UNIX 套接字,因此我不知道这是否是解决此问题的正确方法。
一个进程接收数据(未格式化的,二进制的)并应使用数据报协议(protocol)(即类似于带有 AF_INET 的 UDP)通过本地 AF_UNIX 套接字分发此数据。从此进程发送到本地 Unix 套接字的数据应由监听同一套接字的多个客户端接收。接收器的数量可能会有所不同。
为此,使用以下代码创建套接字并向其发送数据(服务器进程):
struct sockaddr_un ipcFile;
memset(&ipcFile, 0, 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(“传输端点未连接”)。我猜这是因为当前没有接收进程正在监听此本地套接字,对吗?
然后,我尝试创建一个连接到这个套接字的客户端。
struct sockaddr_un ipcFile;
memset(&ipcFile, 0, 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));
...
char buf[1024];
int bytes = read(socket, buf, sizeof(buf));
...
close(socket);
此处,绑定(bind)失败(“地址已在使用中”)。那么,我是否需要设置一些套接字选项,或者这通常是错误的方法吗?
提前感谢您提出任何意见/解决方案!
最佳答案
在数据报配置中使用 Unix Domain Socket 有一个技巧。与流套接字(tcp 或 unix 域套接字)不同,数据报套接字需要为服务器和客户端定义端点。当在流套接字中建立连接时,客户端的端点由操作系统隐式创建。无论这对应于临时 TCP/UDP 端口,还是 unix 域的临时 inode,客户端的端点都是为您创建的。这就是为什么您通常不需要为客户端中的流套接字发出对 bind() 的调用。
您看到“地址已在使用”的原因是您告诉客户端绑定(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, 0, 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, 0, sizeof(client_addr));
client_addr.sun_family = AF_UNIX;
strncpy(client_addr.sun_path, client_filename, 104);
// get socket
int sockfd = socket(AF_UNIX, SOCK_DGRAM, 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, buf, sizeof(buf));
...
close(sockfd);
此时您的套接字应该已完全设置。我认为理论上你可以使用 read()
/write()
,但通常我会使用 send()
/recv( )
用于数据报套接字。
通常您会希望在每次调用后检查错误,然后发出 perror()
。当出现问题时,它将极大地帮助您。通常,使用这样的模式:
if ((sockfd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
perror("socket failed");
}
这几乎适用于所有 C 系统调用。
最好的引用资料是 Steven 的《Unix 网络编程》。在第 3 版的第 15.4 节中,第 415-419 页展示了一些示例并列出了许多注意事项。
顺便引用一下
I guess this is because no receiving process is currently listening to this local socket, correct?
我认为您对服务器中 write()
的 ENOTCONN 错误的看法是正确的。 UDP 套接字通常不会提示,因为它无法知道客户端进程是否正在监听。然而,unix 域数据报套接字是不同的。事实上,如果客户端的接收缓冲区已满,write()
将实际阻塞而不是丢弃数据包。这使得 unix 域数据报套接字的 IPC 优于 UDP,因为 UDP 在负载下肯定会丢弃数据包,即使在本地主机上也是如此。另一方面,这意味着您必须小心写得快和读得慢的人。
关于c - Unix 域套接字 : Using datagram communication between one server process and several client processes,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3324619/
这里是两个人进行通信。是根据ip来判断的,xp与xp之间没有问题,我win7和xp有问题(已解决 关闭防火墙,如果是内网 网段要一致) 复制代码代码如下: impor
This question already has answers here: Why changing value of SO_RCVBUF doesn't work? (2个答案) 9个月前关闭。
我最近深入研究了使用 java 的套接字编程,我有一些一般性的问题。 有一个 bind() 方法,以及一个 connect() 和 disconnect()。没有解除绑定(bind)()。这是因为断开
我正在使用 QUdpSocket 从服务器接收数据。当我使用 SFML 接收数据时,我可以通过 SocketUdp 接收数据,但是使用 qt 它不起作用。 void TheClass::Bind()
Sockets are full-duplex communication channels between processes either local to the same host machi
我有一个在发送方和接收方上运行的应用程序,使用 UDP 协议(protocol)。 UDP 缓冲区大小约为 70 或 1024 字节,因此不会发生 UDP 碎片。 从 ifconfig/sar 级别,
我正在使用连接在 10G 以太网链路上的专用硬件。我有一些关于处理传入数据报的问题,如下: 如果 NIC 发现不正确的链路级以太网 CRC 会怎样?一些搜索表明错误可能不会被可靠地报告(例如 here
“流类型”套接字和“数据报”套接字类型有什么区别? 最佳答案 简短的回答:消息边界和连接。 使用流套接字,您可以写入两条 5 字节消息并最终读取一条 10 字节消息。这是因为您写入的数据只是放入单个流
在 Linux、Ubuntu 14.04 中:我正在编写一个实现套接字的代码来发送纯 UDP 数据报,其中包括 UDP header +有效负载,没有 IP header 的任何部分。 我已经创建了套
我读到应该在 Buffer 类上使用 ByteBuffer (java.nio) 来读取数据,因为它更高效 (?)。我的问题围绕着一个 UDP 客户端,它从多播地址读取数据包并将它们处理成原始对象。从
在 Netty 4 中,没有 Nio/Epoll/DatagramServerChannel 实现,因此无法创建监听 UDP 连接的 ServerBootstrap。 所以,基本上我的问题如下:为什么
这个问题NOT是关于STREAM类型和DATAGRAM类型INTERNET套接字的区别。我知道 STREAM 套接字使用 TCP,数据报套接字使用 UDP 以及所有 TCP、UDP 内容、按顺序到达的
免责声明:这不是一个“如何”的问题。作为背景信息,我更想知道实际使用的不同实际做法是什么。 我们知道 UDP 没有像 TCP 那样的 PMTU 发现。因此,我看到了几种避免使用 UDP 产生 IP 碎
在 recv() 's手册页我发现在这种情况下返回值可以为零: Datagram sockets in various domains (e.g., the UNIX and Internetdoma
我正在使用Alpakkas UDP.bindFlow将传入的UDP数据报转发到Kafka代理。正在发送这些数据报的旧版应用程序需要从与发送消息相同的端口进行UDP响应。我正在努力为这种行为建模,因为这
connect的手册说: If the socket sockfd is of type SOCK_DGRAM then addr is the address to which datagrams
我想在 Linux 上的几个进程之间建立 IPC 连接。我以前从未使用过 UNIX 套接字,因此我不知道这是否是解决此问题的正确方法。 一个进程接收数据(未格式化的,二进制的)并应使用数据报协议(pr
在 Linux 2.6.34 ppc 系统上,在某些情况下的多进程应用程序中,两个 PF_UNIX 套接字之间的 sendto() 返回 -1 和 errno EPERM。我可以在手册页中找到的此上下
我有一段代码使用 Unix 域套接字和 sendmsg/recvmsg 在两个进程之间发送 fd。此代码需要在 Linux 和 Mac 上运行(它针对两个平台分别编译)。我正在使用 SOCK_DGRA
我是一名优秀的程序员,十分优秀!