自动命名AF_UNIX本地数据报套接字?
我正在通过unix本地套接字(AF_UNIX地址族,即不是UDP)上的数据报实现简单的服务。服务器绑定到一个公共地址,并且可以很好地接收请求。不幸的是,在回答问题时,除非客户端也受到约束,否则" sendto"将失败。 (常见错误是"运输端点未连接")。
绑定到某个随机名称(基于文件系统或者抽象)的工作方式。但我想避免这种情况:我该保证谁选的名字不会冲突?
Unix套接字的流模式文档告诉我们,如果还没有抽象名称,则将在"连接"时为其分配一个抽象名称。这样的功能是否可用于面向数据报的套接字?
解决方案
我不确定我是否完全理解问题,但这是我刚刚编写的回显服务器的数据报实现。我们可以看到服务器在从其发送的相同IP / PORT上响应客户端。
这是代码
一,服务器(监听器)
from socket import * import time class Listener: def __init__(self, port): self.port = port self.buffer = 102400 def listen(self): sock = socket(AF_INET, SOCK_DGRAM) sock.bind(('', self.port)) while 1: data, addr = sock.recvfrom(self.buffer) print "Received: " + data print "sending to %s" % addr[0] print "sending data %s" % data time.sleep(0.25) #print addr # will tell you what IP address the request came from and port sock.sendto(data, (addr[0], addr[1])) print "sent" sock.close() if __name__ == "__main__": l = Listener(1975) l.listen()
现在,客户端(发送方)从侦听器接收响应
from socket import * from time import sleep class Sender: def __init__(self, server): self.port = 1975 self.server = server self.buffer = 102400 def sendPacket(self, packet): sock = socket(AF_INET, SOCK_DGRAM) sock.settimeout(10.75) sock.sendto(packet, (self.server, int(self.port))) while 1: print "waiting for response" data, addr = sock.recvfrom(self.buffer) sock.close() return data if __name__ == "__main__": s = Sender("127.0.0.1") response = s.sendPacket("Hello, world!") print response
我假设我们正在运行Linux;我不知道此建议是否适用于SunOS或者任何UNIX。
首先,答案:在socket()之后,connect()或者first sendto()之前,尝试添加以下代码:
struct sockaddr_un me; me.sun_family = AF_UNIX; int result = bind(fd, (void*)&me, sizeof(short));
现在,进行解释:unix(7)手册页指出:
When a socket is connected and it doesn’t already have a local address a unique address in the abstract namespace will be generated automatically.
可悲的是,手册页位于。
检查Linux源代码,我们看到,如果在套接字标志中设置了SOCK_PASSCRED,则unix_dgram_connect()仅调用unix_autobind()。由于我不知道SOCK_PASSCRED是什么,现在是凌晨1:00,因此我需要寻找另一种解决方案。
检查unix_bind时,我注意到如果传入的大小等于" sizeof(short)",则unix_bind会调用unix_autobind。因此,上面的解决方案。
祝你好运,早上好。
抢
回应迟了一点,但是对于像我一样使用google的人来说。 Rob Adam的答案帮助我得到了"真正的"答案:只需使用set(级别SO_SOCKET,请参见man 7 unix)将SO_PASSCRED设置为1. 就不需要傻傻的绑定。
我在PHP中使用了它,但是没有定义SO_PASSCRED(愚蠢的PHP)。但是,如果我们自己定义它,它仍然可以工作。在我的计算机上,它的值为16,我认为它将非常方便地工作。