Python asyncore socket客户端开发基本使用

Posted LinuxProbe19

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python asyncore socket客户端开发基本使用相关的知识,希望对你有一定的参考价值。

导读 asyncore库是python的一个标准库,提供了以异步的方式写入套接字服务的客户端和服务器的基础结构,这篇文章主要介绍了Python asyncore socket客户端开发基本使用,需要的朋友可以参考下
介绍

asyncore库是python的一个标准库,提供了以异步的方式写入套接字服务的客户端和服务器的基础结构。操作网络的时候可以直接使用socket等底层的库,但是asyncore使得我们可以更加方便的操作网络,避免直接使用socket,select,poll等工具时需要面对的复杂情况。

1.定义类并且继承 asyncore.dispatcher
class SocketClient(asyncore.dispatcher):
2.实现类中的回调代码
调用父类方法

asyncore.dispatcher.__init__(self)

创建 socket 对象
self.create_socket()
连接服务器
address = (host, port)
self.connect(address)
实现 handle_connect 回调函数

当socket 连接服务器成功时回调该函数

def handle_connect(self):
    print(\'连接成功\')
实现 writable 回调函数

描述是否有数据需要被发送到服务器。返回值为True表示可写,False 表示不可写。

如果不识闲默认返回为 True,当返回True时,回调函数handle_write将被触发

def writable(self):
    return False
实现 handle_write 回调函数

当有数据需要发送时 (writable 回调函数返回 True时),

该函数被触发,通常情况下在该函数中编写send方法发送数据

def handle_write(self):
    # 内部实现对服务器发送数据
    # 调用 send 方法,参数是字节数据
    self.send(\'hello world\'.encode(\'utf-8\'))
实现 readable 回调函数

描述是否有数据从服务端读取。返回True标识有数据需要读取,

False表示没有数据需要被读取,当不实现默认返回True,

当返回True时,handle_read将被触发

def readable(self):
    # 表示有数据需要读取
    return True
实现 handle_read 回调函数

当有数据需要读取时(readable 回调函数返回True时),

该函数被触发,通常情况下在该函数中编写recv方法接收数据

def handle_read(self):
    # 主动读取接收数据 参数是需要接收数据长度
    result = self.recv(8000)
    print(result)
实现 handle_error 回调函数

当程序运行过程发生异常时回调

def handle_error(self):
    # 编写处理错误方法
    t, e, trace = sys.exc_info()
    print(t, e, trace)
实现 handle_close 回调函数

当连接被关闭时触发

def handle_close(self):
    print(\'连接关闭\')
    # 执行关闭
    self.close()
3.创建对象并且执行 asyncore.loop 进入运行循环

timeout为一次循环所用的时间,也就是超时时间。

client = SocketClient(\'127.0.0.1\', 9000)
# 开始启动运行循环
asyncore.loop(timeout=10)
服务端示例代码
import asyncore
import socket
class EchoHandler(asyncore.dispatcher_with_send):
  
    def handle_read(self):
        data = self.recv(8192)
        if data:
            self.send(data)
  
  
class EchoServer(asyncore.dispatcher):
  
    def __init__(self, host, port):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.set_reuse_addr()
        self.bind((host, port))
        # 监听连接参数指定排队的最大连接数和应至少为1; 最大值取决于系统(通常为5)。
        self.listen(5)
  
    \'\'\'
    当与发起对本地端点的 connect() 调用的新远程端点已建立连接时会在侦听通道(被动打开方)上被调用。 
    sock 是可被用于在连接上发送和接收数据的 新建 套接字对象,
    而 addr 是绑定到连接另一端的套接字的地址。
    \'\'\'
    def handle_accept(self):
        pair = self.accept()
        if pair is not None:
            sock, addr = pair
            print(\'连接来自于 %s\' % repr(addr))
            # 连接成功后 给客户端发送消息
            handler = EchoHandler(sock)
            handler.send(\'hello world\'.encode(\'utf-8\'))
  
if __name__ == \'__main__\':
    server = EchoServer(\'127.0.0.1\', 9000)
    asyncore.loop()
运行结果

服务端:

客户端:

注意:

本文章使用python3.7版本,3.10版本已经移除此模块,之后可使用asyncio模块。

至此结束,本文章只做了一个基本使用讲解,可以查看借鉴使用,若想要做消息还差的很多。

本文地址:https://www.linuxprobe.com/python-asyncore-socket.html

Python异步套接字recv不起作用

【中文标题】Python异步套接字recv不起作用【英文标题】:Python async socket recv not working 【发布时间】:2016-06-03 08:15:47 【问题描述】:

这是一个简单的客户端,它连接并发送一条短信:

class Client(asyncore.dispatcher):

    def __init__(self, host, port):
        asyncore.dispatcher.__init__(self)
        self.create_socket()
        self.connect( (host, port) )
        self.buffer = bytes("hello world", 'ascii')

    def handle_connect(self):
        pass

    def handle_close(self):
        self.close()

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

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

    def writable(self):
        return True

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


client = Client('localhost', 8080)
asyncore.loop()

这是必须接收消息并将其回显的服务器:

class Server(asyncore.dispatcher):
    def __init__(self, host, port):
        asyncore.dispatcher.__init__(self)
        self.create_socket()
        self.set_reuse_addr()
        self.bind((host, port))
        self.listen(5)

    def handle_read(self):
        self.buffer = self.recv(4096)
        while True:
            partial = self.recv(4096)
            print('Partial', partial)
            if not partial:
                break
            self.buffer += partial

    def readable(self):
        return True

    def handle_write(self):
        pass

    def handle_accepted(self, sock, addr):
        print('Incoming connection from %s' % repr(addr))
        self.handle_read()
        print(self.buffer)


if __name__ == "__main__":
    server = Server("localhost", 8080)
    asyncore.loop()

问题是服务器没有读取任何内容。当我打印 self.buffer 时,输出是:

b''

我做错了什么?

【问题讨论】:

你的服务器代码中的self.accept()在哪里? 我认为异步套接字不需要这样做:docs.python.org/3/library/asyncore.html 我有上一个示例中的这段代码。并且连接被接受,因为 handle_accepted 中的打印语句将其打印出来。 好的,我看到了。我已经阅读了 Py 2 的文档。但它认为,您应该使用单独的类来处理与客户端的连接。如果你一起写,它不可能是异步的。 【参考方案1】:

首先,您需要两个处理程序:一个用于服务器套接字(您期望只有accept),一个用于实际的通信套接字。另外,readhandle_read中只能调用一次;如果你调用它两次,第二次调用可能会阻塞,这在异步编程中是不允许的。不过不用担心;如果您的读取没有得到所有内容,一旦您的读取处理程序返回,您将立即再次收到通知。

import asyncore

class Handler(asyncore.dispatcher):
    def __init__(self, sock):
        self.buffer = b''
        super().__init__(sock)

    def handle_read(self):
        self.buffer += self.recv(4096)
        print('current buffer: %r' % self.buffer)


class Server(asyncore.dispatcher):
    def __init__(self, host, port):
        asyncore.dispatcher.__init__(self)
        self.create_socket()
        self.set_reuse_addr()
        self.bind((host, port))
        self.listen(5)

    def handle_accepted(self, sock, addr):
        print('Incoming connection from %s' % repr(addr))
        Handler(sock)


if __name__ == "__main__":
    server = Server("localhost", 1234)
    asyncore.loop()

【讨论】:

以上是关于Python asyncore socket客户端开发基本使用的主要内容,如果未能解决你的问题,请参考以下文章

python 实现聊天室

Python聊天室

Python异步套接字recv不起作用

Python异步通信模块asyncore

python asyncore

Python异步和dbus