pythontcp服务器框架_python tcp udp 服务器框架

事件驱动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)

(b'Tue Sep 18 14:29:23 2012', ('127.0.0.1', 14000))

>>> s.sendto(b'Hello',('localhost',15000))

5

>>> s.recvfrom(128)

(b'Hello', ('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 loop's 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 loop's 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或类似工具连接,它会将你发送的消息回显给你。并且它能很轻松的处理多客户端连接。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值