Hunter的大杂烩 技术学习笔记

2020-03-18

Python 2.7下的非阻塞tcp client实现

Filed under: 技术话题 — hunter @ 5:05 pm

因为要实现一个简单的网络服务性能测试工具,需要衡量TCP CONNECT环节耗时,发现目前网上对于python 2下的非阻塞connect/send/recv介绍很少,于是自己实现了一个

参考:

https://docs.python.org/2/howto/sockets.html#sockets

https://docs.python.org/2/howto/sockets.html#non-blocking-sockets

https://learnku.com/docs/pymotw/select-wait-for-io-efficiently/3429

https://stackoverflow.com/questions/8277970/what-are-possible-reason-for-socket-error-einprogress-in-solaris

https://www.cnblogs.com/MnCu8261/p/6403340.html

https://gist.github.com/hduffddybz/daa4c931f6ea0bd7ed93

[code language=”python”]

# -*- coding: utf-8 -*
"""
CopyLeft!2020 by hunter
转载请保留此文件头
用途:
异步tcp client,基于python 2.7
"""

import socket, select
import errno

class TCPClient(object):
def __init__(self, host, port, handler=None):
self.host = host
self.port = port
self.handler = handler
self.sock_server = None

def connect(self, timeout):
try:
self.sock_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock_server.setblocking(False)
err_code = self.sock_server.connect_ex((self.host, self.port))
if err_code != errno.EINPROGRESS and err_code != errno.EWOULDBLOCK:
print errno
return False
if err_code == 0:
return True

inputs = [self.sock_server]
while True:
infds, outfds, errfds = select.select(inputs, inputs, inputs, timeout)
#timeout
if len(infds) == 0 and len(outfds) == 0 and len(errfds) == 0:
return False
if len(errfds) != 0:
return False
if len(infds) != 0:
break
if len(outfds) != 0:
break

return True
except Exception as e:
print(‘Connect Error. %s’ % e)
return False

def stop(self):
if self.sock_server is not None:
self.sock_server.close()

def send(self, msg, timeout):
try:
outputs = [self.sock_server]
total_sent = 0
msg_len = len(msg)
while total_sent < msg_len:
infds, outfds, errfds = select.select([], outputs, outputs, timeout)
#timeout
if len(infds) == 0 and len(outfds) == 0 and len(errfds) == 0:
raise RuntimeError("timeout.")
if len(outfds) != 0:
sent = self.sock_server.send(msg[total_sent:])
if sent == 0:
raise RuntimeError("socket connection broken")
total_sent = total_sent + sent
if len(errfds) != 0:
raise RuntimeError("send exception.")
return True
except Exception as e:
print(‘Send Error. %s’ % e)
return False

def receive(self, pkg_max_len, timeout):
try:
chunks = []
bytes_recd = 0
inputs = [self.sock_server]
while bytes_recd < pkg_max_len:
infds, outfds, errfds = select.select(inputs, [], inputs, timeout)
#timeout
if len(infds) == 0 and len(outfds) == 0 and len(errfds) == 0:
raise RuntimeError("timeout.")
if len(infds) > 0:
chunk = self.sock_server.recv(min(pkg_max_len – bytes_recd, 2048))
if chunk == ”:
raise RuntimeError("socket connection broken")
chunks.append(chunk)
bytes_recd = bytes_recd + len(chunk)
if len(errfds) != 0:
raise RuntimeError("send exception.")
return ”.join(chunks)
except Exception as e:
print(‘Recv Error. %s’ % e)
return None

[/code]

No Comments

No comments yet.

RSS feed for comments on this post.

Sorry, the comment form is closed at this time.

Powered by WordPress