tornado实现高性能无阻塞udp通信(2)——实现异步udp客户端
来源:互联网 发布:java io应用实例 编辑:程序博客网 时间:2024/05/21 22:21
上一篇实现了基于tornado的高性能无阻塞udp服务器,然而光有服务器还是不够的,那么这篇就来实现一个基于tornado的异步udp客户端。
先来分析下客户端的任务:因为整个系统是用来进行代替传统web api的,所以这里的udp客户端不是只发一个包就万事大吉了,而是发出一个包后等待server端返回结果。看似很简单的任务放到tornado上就没那么简单了。传统多进程模型每个访客对应一个进程,在这种模型下我们可以发出udp包之后阻塞该进程等待结果返回。然而对于tornado这种单进程模型,阻塞无异于自杀,所以需要异步写法从而使得发出去一个包之后,tornado进程迅速去处理其他请求等到结果返回时再通过回调函数继续处理该请求。
分析完之后就开始动手啦。先简单封装一个UDPRequest,便于后面处理。只有一点要注意的,数据以'\n\r\n\r'结尾。
class UDPRequest(object): def __init__(self,addr,port,data): self.addr = addr self.port = port self.data = data def __getattribute__(self,name): data = object.__getattribute__(self,name) if name == 'data' and data.rfind('\r\n\r\n') != len(data)-4 or len(data) < 4: data += '\r\n\r\n' return data
class _UDPConnection(object): def __init__(self,io_loop,client,request,release_callback, final_callback,max_buffer_size): self.start_time = time.time() self.io_loop = io_loop self.client = client self.request = request self.release_callback = release_callback self.final_callback = final_callback addrinfo = socket.getaddrinfo(request.addr,request.port, socket.AF_INET,socket.SOCK_DGRAM,0,0) af,socktype,proto,canonname,sockaddr = addrinfo[0] self.stream = IOStream(socket.socket(af,socktype,proto), io_loop=self.io_loop,max_buffer_size=2500) self.stream.connect(sockaddr,self._on_connect) def _on_connect(self): self.stream.write(self.request.data) self.stream.read_until('\r\n\r\n',self._on_response) def _on_response(self,data): if self.release_callback is not None: release_callback = self.release_callback self.release_callback = None release_callback() self.stream.close()
简单讲一下_UDPConnection的思路,正如前面所说的,发送出数据包之后就认为这个socket已经和server建立的一对一的'链接',于是利用这个socket构造一个IOStream,让tornado帮我们实现无阻塞io操作。一旦这个socket'链接好',IOStream便会调用 _on_connect()函数,在_on_connect()函数中首先发送数据,然后设定一旦读到'\r\n\r\n'就认为数据包结束了便调用_on_response()函数。
ps:解释一下红字‘链接好’,并不是传统意义上的三次握手建立链接,实际上udp是不用链接的,这里只是为了兼容默认的IOStream,调用这个函数只是为了修改IOStream内部的一个参数让IOStream以为链接已经建立好了。
最后把client的代码放上来
class AsyncUDPClient(object): def __init__(self, io_loop=None): self.io_loop = io_loop or IOLoop.instance() self.max_clients = 10 self.queue = collections.deque() self.active = {} self.max_buffer_size = 2500 def fetch(self,request,callback,**kwargs): callback = stack_context.wrap(callback) self.queue.append((request,callback)) self._process_queue() def _process_queue(self): with stack_context.NullContext(): while self.queue and len(self.active) < self.max_clients: request, callback = self.queue.popleft() key = object() self.active[key] = (request,callback) _UDPConnection(self.io_loop,self,request, functools.partial(self._release_fetch,key), callback, self.max_buffer_size) def _release_fetch(self,key): del self.active[key] self._process_queue()
不难理解,这个client就是生成_UDPConnection对象
到这里异步udp客户端就完成了,使用方法和官方的httpclient一模一样。当然,这里放出来的代码还有很多细节例如超时,丢包之类的没有处理,所以想用在生产环境的话还需要完善一些细节。
- tornado实现高性能无阻塞udp通信(2)——实现异步udp客户端
- tornado实现高性能无阻塞udp通信(1)——server端实现
- UDP通信编程------利用CAsyncSock类实现UDP异步通信
- UDP实现服务器与客户端通信
- TCP/UDP客户端服务器实现通信
- socket udp 客户端实现
- Udp实现通信DEMO
- UDP通信C++实现
- python实现UDP通信
- C++实现UDP通信。。
- Java实现UDP通信
- Android实现UDP通信
- Qt-----实现Udp通信
- UDP通信实现
- socket实现UDP通信
- Java实现UDP通信
- C#实现UDP通信
- 利用IO完成端口实现高性能的UDP或TCP通信
- C/S通信交互之Cocos2dx使用BSD Socket与Mina手机网游通信框架
- Android App 性能优化
- 【Cocos2dx通信(Http&Socket)相关编译到Android细节总结】编译加入curl关联lib与头文件 && 解决pthread的cancel函数NDK不支持,找不到sockaddr_i
- PAT 1016 Phone Bills
- 常用挂载命令mount
- tornado实现高性能无阻塞udp通信(2)——实现异步udp客户端
- ZOJ 3696 Alien's Organ / 泊松分布
- C - Unions
- Linux进程分析
- (四)继承
- 题目1200:最大的两个数
- 大年初一
- Python中的格式化打印
- sudo命令详解