一个进程接收数据(未格式化,二进制),并将使用数据报协议(即类似于具有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);
这里,绑定失败(“地址已在使用中”)。那么,我需要设置一些套接字选项,还是这通常是错误的方法?
感谢您的任何意见/解决方案!
您看到“地址已在使用”的原因是因为您要告诉客户端绑定到与服务器相同的地址。 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上肯定会丢弃数据包。另一方面,这意味着你必须小心快速的作家和慢读者。