当前位置 : 主页 > 网络编程 > 其它编程 >

pythontcp服务器框架_pythontcpudp服务器框架

来源:互联网 收集:自由互联 发布时间:2023-07-02
事件驱动IO本质上来讲就是将基本IO操作(比如读和写)转化为你程序需要处理的事件。例如当数据在某个socket上被接受后它会转换成一个receive 事件驱动I/O本质上来讲就是将基本I/O操作(比
事件驱动IO本质上来讲就是将基本IO操作(比如读和写)转化为你程序需要处理的事件。例如当数据在某个socket上被接受后它会转换成一个receive

事件驱动I/O本质上来讲就是将基本I/O操作(比如读和写)转化为你程序需要处理的事件。 例如当数据在某个socket上被接受后它会转换成一个 receive 事件然后被你定义的回调方法或函数来处理。 作为一个可能的起始点一个事件驱动的框架可能会以一个实现了一系列基本事件处理器方法的基类开始

class EventHandler:

def fileno(self):

Return the associated file descriptor

raise NotImplemented(must implement)

def wants_to_receive(self):

Return True if receiving is allowed

return False

def handle_receive(self):

Perform the receive operation

pass

def wants_to_send(self):

Return True if sending is requested

return False

def handle_send(self):

Send outgoing data

pass

这个类的实例作为插件被放入类似下面这样的事件循环中

import select

def event_loop(handlers):

while True:

wants_recv [h for h in handlers if h.wants_to_receive()]

wants_send [h for h in handlers if h.wants_to_send()]

can_recv, can_send, _ select.select(wants_recv, wants_send, [])

for h in can_recv:

h.handle_receive()

for h in can_send:

h.handle_send()

事件循环的关键部分是 select() 调用它会不断轮询文件描述符从而激活它。 在调用 select() 之前事件循环会询问所有的处理器来决定哪一个想接受或发生。 然后它将结果列表提供给 select() 。然后 select() 返回准备接受或发送的对象组成的列表。 然后相应的 handle_receive() 或 handle_send() 方法被触发。

编写应用程序的时候EventHandler 的实例会被创建。例如下面是两个简单的基于UDP网络服务的处理器例子

import socket

import time

class UDPServer(EventHandler):

def __init__(self, address):

self.sock socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

self.sock.bind(address)

def fileno(self):

return self.sock.fileno()

def wants_to_receive(self):

return True

class UDPTimeServer(UDPServer):

def handle_receive(self):

msg, addr self.sock.recvfrom(1)

self.sock.sendto(time.ctime().encode(ascii), addr)

class UDPEchoServer(UDPServer):

def handle_receive(self):

msg, addr self.sock.recvfrom(8192)

self.sock.sendto(msg, addr)

if __name__ __main__:

handlers [ UDPTimeServer((,14000)), UDPEchoServer((,15000)) ]

event_loop(handlers)

测试这段代码试着从另外一个Python解释器连接它

>>> from socket import *

>>> s socket(AF_INET, SOCK_DGRAM)

>>> s.sendto(b,(localhost,14000))

0

>>> s.recvfrom(128)

(bTue Sep 18 14:29:23 2012, (127.0.0.1, 14000))

>>> s.sendto(bHello,(localhost,15000))

5

>>> s.recvfrom(128)

(bHello, (127.0.0.1, 15000))

>>>

实现一个TCP服务器会更加复杂一点因为每一个客户端都要初始化一个新的处理器对象。 下面是一个TCP应答客户端例子

class TCPServer(EventHandler):

def __init__(self, address, client_handler, handler_list):

self.sock socket.socket(socket.AF_INET, socket.SOCK_STREAM)

self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)

self.sock.bind(address)

self.sock.listen(1)

self.client_handler client_handler

self.handler_list handler_list

def fileno(self):

return self.sock.fileno()

def wants_to_receive(self):

return True

def handle_receive(self):

client, addr self.sock.accept()

# Add the client to the event loops handler list

self.handler_list.append(self.client_handler(client, self.handler_list))

class TCPClient(EventHandler):

def __init__(self, sock, handler_list):

self.sock sock

self.handler_list handler_list

self.outgoing bytearray()

def fileno(self):

return self.sock.fileno()

def close(self):

self.sock.close()

# Remove myself from the event loops handler list

self.handler_list.remove(self)

def wants_to_send(self):

return True if self.outgoing else False

def handle_send(self):

nsent self.sock.send(self.outgoing)

self.outgoing self.outgoing[nsent:]

class TCPEchoClient(TCPClient):

def wants_to_receive(self):

return True

def handle_receive(self):

data self.sock.recv(8192)

if not data:

self.close()

else:

self.outgoing.extend(data)

if __name__ __main__:

handlers []

handlers.append(TCPServer((,16000), TCPEchoClient, handlers))

event_loop(handlers)

TCP例子的关键点是从处理器中列表增加和删除客户端的操作。 对每一个连接一个新的处理器被创建并加到列表中。当连接被关闭后每个客户端负责将其从列表中删除。 如果你运行程序并试着用Telnet或类似工具连接它会将你发送的消息回显给你。并且它能很轻松的处理多客户端连接。

上一篇:《行客叹》翻译原文赏析诗人现代马一浮
下一篇:没有了
网友评论