UNIX 数据报套接字向发送方返回数据 [英] UNIX Datagram Socket return data to sender

查看:24
本文介绍了UNIX 数据报套接字向发送方返回数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有些东西我无法理解.我创建了一个 unix 数据报套接字:

There is something i can't get my head arround. I've created a unix datagram socket with:

self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
self.socket.bind(SOCKET_FILE)

稍后在代码中我收到写入套接字的消息

Later in the code i receive messages written to the socket with

data, addr = self.socket.recvfrom(4096)

但是 addr 似乎一直都是 None.但我需要它来发回响应.
如何使用 unix 数据报套接字实现回写发送方?

But addr appears to be None all the time. But i need it to send back a response.
How can i achieve writing back to the sender with unix datagram sockets?

感谢您的回答

推荐答案

假设我们有一个服务器:

Suppose we have a server:

# server.py
import os
import socket

SOCKET_FILE = "mysocket-server"
s = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
s.bind(SOCKET_FILE)
data, addr = s.recvfrom(4096)
s.close()
os.unlink(SOCKET_FILE)
print(data, addr)

如果客户端连接并发送消息而没有将自己的名称绑定到套接字,如下所示:

If a client connects and sends a message without binding its own name to the socket, like so:

# client.py
import socket

SOCKET_FILE = "mysocket-server"
sk = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
sk.sendto("hello", SOCKET_FILE)
sk.close()

然后消息将匿名发送,客户端没有绑定地址(即,使用addr == None).请注意,这与 IP 数据报套接字不同,IP 数据报套接字会在您发送数据后立即自动绑定到新地址(即主机地址和端口号).

then the message will be sent anonymously with no address bound on the client side (i.e., with addr == None). Note that this is different from IP datagram sockets which are automatically bound to a fresh address (i.e., host address and port number) as soon as you send data.

对于这种通过 Unix 数据报套接字的匿名消息,客户端没有分配地址,也没有服务器可以向发送方发送返回数据的机制.

For such anonymous messages over Unix datagram sockets, the client has no assigned address, and there is no mechanism by which the server can send return data to the sender.

最简单的解决方案是让客户端将自己的私有名称绑定到套接字:

The simplest solution is for the client to bind it's own private name to the socket:

# client2.py
import os
import socket

SERVER_FILE = "mysocket-server"
CLIENT_FILE = "mysocket-client"

sk = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
sk.bind(CLIENT_FILE)
sk.sendto("hello", SERVER_FILE)
data, addr = sk.recvfrom(4096)
print(data,addr)
sk.close()
os.unlink(CLIENT_FILE)

然后,使用以下修改后的服务器:

Then, using the following modified server:

# server2.py
import os
import socket

SOCKET_FILE = "mysocket-server"
s = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
s.bind(SOCKET_FILE)

data, addr = s.recvfrom(4096)
if addr is not None:
s.sendto("world", addr)
print(data, addr)

s.close()
os.unlink(SOCKET_FILE)

你可以看到双向通信是可能的.

you can see that two-way communication is possible.

在 Linux 上,有一个抽象命名空间"扩展(参见 unix(7) 手册页),这意味着客户端也可以使用 sk.bind(""),像这样:

On Linux, there's an "abstract namespace" extension (see the unix(7) manpage) which means the client can also bind to an empty name with sk.bind(""), like so:

# client3.py
import socket

SERVER_FILE = "mysocket-server"

sk = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
sk.bind("")
sk.sendto("hello", SERVER_FILE)
data, addr = sk.recvfrom(4096)
print(data,addr)
sk.close()

这会自动将客户端绑定到一个新的抽象套接字地址",这在某种程度上模拟了 IP 数据报套接字已经做的事情.

This automatically binds the client to a fresh "abstract socket address", which sort of emulates what IP datagram sockets already do.

作为替代方法,您可以使用 SOCK_SEQPACKET 代替 SOCK_DGRAM.这会自动构建双向连接(如SOCK_STREAM)但保留消息边界(如SOCK_DATAGRAM).这是一个服务器,它在循环中接受来自客户端的连接,接收和响应来自每个客户端的两个数据包.

As an alternative approach, you can use SOCK_SEQPACKET in place of SOCK_DGRAM. This automatically constructs a two-way connection (like SOCK_STREAM) but preserves the message boundaries (like SOCK_DATAGRAM). Here's a server that accepts connections from clients in a loop, receiving and responding to two packets from each client.

# server4.py
import os
import socket

SOCKET_FILE = "mysocket-server"
s = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
s.bind(SOCKET_FILE)
s.listen(5)

try:
while True:
    (t, _) = s.accept()
    print(t.recv(4096))
    t.send("sun")
    print(t.recv(4096))
    t.send("moon")
    t.close()
finally:
os.unlink(SOCKET_FILE)

以下客户端演示了响应数据包是分开的:

The following client demonstrates that the response packets are kept separate:

# client4.py
import socket

SERVER_FILE = "mysocket-server"

sk = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
sk.connect(SERVER_FILE)
sk.send("hello")
sk.send("goodbye")
print(sk.recv(4096))
print(sk.recv(4096))
sk.close()

在这里,server4.py 不是一个很好的服务器设计,因为行为不良的客户端可能会阻塞,阻止服务器为任何其他客户端提供服务.真正的服务器可能会使用单独的工作线程来保持运行速度,以应对缓慢的客户端.

Here, server4.py isn't a great server design, since a badly behaved client can block, preventing the server from serving any other clients. A real server might use separate worker threads to keep running in the face of slow clients.

这篇关于UNIX 数据报套接字向发送方返回数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆