首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >python asyncore使用AF_UNIX套接字的问题

python asyncore使用AF_UNIX套接字的问题
EN

Stack Overflow用户
提问于 2011-05-13 23:54:30
回答 2查看 2.8K关注 0票数 3

我在使用带有AF_UNIX套接字的异步内核时遇到一些问题。这段代码

代码语言:javascript
复制
import asyncore, socket, os
class testselect(asyncore.dispatcher):

    path = '/tmp/mysocket'

    def __init__(self):

        asyncore.dispatcher.__init__(self)

        self.create_socket(socket.AF_UNIX, socket.SOCK_DGRAM)
        self.bind(self.path)
        self.buffer = 'buffer'

    def handle_connect(self):

        print 'handle_connect'
        pass

    def handle_close(self):
        print 'handle_close'
        if os.path.exists(self.path)       
             os.remove(self.path)
        self.close()

    def handle_read(self):
        print 'handle_read'
        print self.recv(8192)

    def writable(self):
        print 'writable'
        return (len(self.buffer) > 0)

    def handle_write(self):
        print 'handle_write'
        sent = self.send(self.buffer)
        self.buffer = self.buffer[sent:]


    client = testselect()
    asyncore.loop()

如果我执行代码

代码语言:javascript
复制
 $ python select_prova.py
 writable
 handle_connect
 handle_write
 handle_close
 $  

它会立即退出,不等待读写。如果我更改代码以强制writable()方法始终返回False,它将正确地等待输入,且我可以像这样与套接字通信

代码语言:javascript
复制
 $ socat readline UNIX:/tmp/mysocket

但仅用于读取(写入在逻辑上不起作用,因为writable()返回False)。我的代码中是否有错误,或者我不能使用asyncore/select()来管理AF_UNIX套接字?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-05-14 00:42:05

注意正如另一个答案所指出的,当您发送数据报时,您需要指定接收者。按照现在的情况,您的testselect类看起来更像是客户端而不是服务器。

查看其中的一些asyncore examples,以找到您可以复制的服务器模式。TimeChannel示例更接近您的期望--将socket.AF_INET更改为socket.AF_UNIX,并使用绑定地址的套接字路径,使其使用UNIX域套接字。

您正在设置socket.SOCK_DGRAM,它通常指示UDP INET套接字的创建。Unix域套接字是IPC的一种形式。您应该将其更改为socket.SOCK_STREAM,调用self.listen([backlog]),实现handle_accept()等。

如果您确实打算将SOCK_DGRAM与AF_UNIX一起使用,服务器退出的原因是它在启动时立即指示writable,这会导致handle_write运行,并立即发送包含'buffer'的数据包。

如果希望服务器等到收到包后再进行回复,请在handle_connecthandle_read中设置缓冲区

代码语言:javascript
复制
    def __init__(self):
        ...
        self.buffer = ''

    def handle_connect(self):
        self.buffer = 'buffer'

现在,当您启动服务器时,它将一直等待,直到收到来自socat的数据包。

我已经重写了你的例子,让它更像你的indend:

代码语言:javascript
复制
import asyncore, socket, os

class testselect(asyncore.dispatcher):

    path = '/tmp/mysocket'

    def __init__(self):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_UNIX, socket.SOCK_STREAM)
        self.set_reuse_addr()
        self.bind(self.path)
        self.listen(5)

    def handle_accept(self):
        client = self.accept()
        if client is None:
            pass
        else:
            handler = testhandler(*client)

class testhandler(asyncore.dispatcher_with_send):

    def __init__(self, sock, addr):
        asyncore.dispatcher_with_send.__init__(self, sock)
        self.addr = addr
        self.buffer = 'greetings'

    def handle_read(self):
        print self.recv(8192)

    def writable(self):
        return (len(self.buffer) > 0)

    def handle_write(self):
        self.send(self.buffer)
        self.buffer = ''

    def handle_close(self):
        self.close()

server = testselect()
try:
    asyncore.loop()
finally:
    if os.path.exists(testselect.path):
        os.unlink(testselect.path)
票数 5
EN

Stack Overflow用户

发布于 2011-05-14 00:55:03

您的困难可以归结为使用SOCK_DGRAM这一事实。据我所知,你基本上不能有效地使用异步内核(没有recvfromsendto)来处理SOCK_DGRAM套接字。此外,socat似乎没有使用SOCK_DGRAM UNIX域套接字的方法。

SOCK_DGRAM套接字没有真正的连接概念,因此它们将始终在select调用中注册为可写。但是,当您实际执行write时,它将失败,因为您没有提供目标地址。

另一个答案的术语是错误的,但基本上是正确的。这里需要使用SOCK_STREAM套接字。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5994521

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档