From 96b39b7197f2808c63fcb6ee58cc7e3007ea3c49 Mon Sep 17 00:00:00 2001 From: Renan Date: Tue, 14 May 2019 16:32:29 -0300 Subject: [PATCH 1/2] Added enable/disable socket tcp_quickack option --- README.md | 8 ++++++++ vxi11/rpc.py | 18 ++++++++++++++---- vxi11/version.py | 2 +- vxi11/vxi11.py | 28 +++++++++++++++++++++++++--- 4 files changed, 48 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index b29063d..db4d631 100644 --- a/README.md +++ b/README.md @@ -68,3 +68,11 @@ and: print(instr.ask("*IDN?")) # returns 'AGILENT TECHNOLOGIES,MSO-X 3014A,MY********,02.35.2013061800' +In case of double acks and retransmissions in Unix Like Systems, disable TCP_QUICKACK is an option: + + import vxi11 + instr = vxi11.Instrument("192.168.1.104") + instr.disable_tcp_quickack() + print(instr.ask("*IDN?")) + # returns 'AGILENT TECHNOLOGIES,MSO7104A,MY********,06.16.0001' + instr.close() \ No newline at end of file diff --git a/vxi11/rpc.py b/vxi11/rpc.py index 9d889a6..8628a39 100644 --- a/vxi11/rpc.py +++ b/vxi11/rpc.py @@ -251,8 +251,9 @@ def recvrecord(sock): # Client using TCP to a specific port class RawTCPClient(Client): - def __init__(self, host, prog, vers, port): + def __init__(self, host, prog, vers, tcp_quickack, port): Client.__init__(self, host, prog, vers, port) + self.tcp_quickack = tcp_quickack self.connect() def connect(self): @@ -264,6 +265,8 @@ def close(self): def do_call(self): call = self.packer.get_buf() + + self.configure_socket_options() sendrecord(self.sock, call) while True: reply = recvrecord(self.sock) @@ -280,6 +283,13 @@ def do_call(self): else: # xid larger than expected - packet from the future? raise RPCError('wrong xid in reply %r instead of %r' % (xid, self.lastxid)) + + #Reset tcp_quickack case it is 0. If tcp_quickack is 1, socket do it automatically after recv or send operations + #Does nothing in Windows OS + def configure_socket_options(self): + if os.name != 'nt': + if self.tcp_quickack == 0: + self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_QUICKACK, 0) # Client using UDP to a specific port @@ -489,7 +499,7 @@ def callit(self, ca): class TCPPortMapperClient(PartialPortMapperClient, RawTCPClient): def __init__(self, host): - RawTCPClient.__init__(self, host, PMAP_PROG, PMAP_VERS, PMAP_PORT) + RawTCPClient.__init__(self, host, PMAP_PROG, PMAP_VERS, 1, PMAP_PORT) PartialPortMapperClient.__init__(self) @@ -511,14 +521,14 @@ def __init__(self, bcastaddr): class TCPClient(RawTCPClient): - def __init__(self, host, prog, vers, port=0): + def __init__(self, host, prog, vers, tcp_quickack, port=0): if port == 0: pmap = TCPPortMapperClient(host) port = pmap.get_port((prog, vers, IPPROTO_TCP, 0)) pmap.close() if port == 0: raise RPCError('program not registered') - RawTCPClient.__init__(self, host, prog, vers, port) + RawTCPClient.__init__(self, host, prog, vers, tcp_quickack, port) class UDPClient(RawUDPClient): diff --git a/vxi11/version.py b/vxi11/version.py index e46aee1..ba6dbaa 100644 --- a/vxi11/version.py +++ b/vxi11/version.py @@ -1 +1 @@ -__version__ = '0.9' +__version__ = '0.95' \ No newline at end of file diff --git a/vxi11/vxi11.py b/vxi11/vxi11.py index 231582d..2fcc90f 100644 --- a/vxi11/vxi11.py +++ b/vxi11/vxi11.py @@ -393,10 +393,10 @@ def done(self): class CoreClient(rpc.TCPClient): - def __init__(self, host, port=0): + def __init__(self, host, tcp_quickack, port=0): self.packer = Packer() self.unpacker = Unpacker('') - rpc.TCPClient.__init__(self, host, DEVICE_CORE_PROG, DEVICE_CORE_VERS, port) + rpc.TCPClient.__init__(self, host, DEVICE_CORE_PROG, DEVICE_CORE_VERS, tcp_quickack, port) def create_link(self, id, lock_device, lock_timeout, name): params = (id, lock_device, lock_timeout, name) @@ -574,6 +574,7 @@ def __init__(self, host, name = None, client_id = None, term_char = None): self.client_id = client_id self.term_char = term_char self.lock_timeout = 10 + self._tcp_quickack = 1 self.timeout = 10 self.abort_port = 0 self.link = None @@ -607,13 +608,34 @@ def lock_timeout(self, val): self._lock_timeout = val self._lock_timeout_ms = int(val * 1000) + @property + def tcp_quickack(self): + return self._tcp_quickack + + def enable_tcp_quickack(self): + #Enable Socket TCP_QUICKACK. This is enabled by default in the socket class. + #Should be enabled/disabled before open() + if self.client is None: + self._tcp_quickack = 1 + else: + raise Vxi11Exception("client already oppened! Use it before open the connection!") + + def disable_tcp_quickack(self): + #Disable Socket TCP_QUICKACK. This should be disabled if your connection is + #having a lot of double acks and retransmissions. Should be enabled/disabled before open() + #This does nothing for Windows OS + if self.client is None: + self._tcp_quickack = 0 + else: + raise Vxi11Exception("client already oppened! Use it before open the connection!") + def open(self): "Open connection to VXI-11 device" if self.link is not None: return if self.client is None: - self.client = CoreClient(self.host) + self.client = CoreClient(self.host, self.tcp_quickack) self.client.sock.settimeout(self.timeout+1) error, link, abort_port, max_recv_size = self.client.create_link( From d928068400b0f2f689dac7dc5224753c20bdae34 Mon Sep 17 00:00:00 2001 From: Renan Date: Tue, 14 May 2019 16:48:45 -0300 Subject: [PATCH 2/2] Update version to original version. --- vxi11/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vxi11/version.py b/vxi11/version.py index ba6dbaa..e46aee1 100644 --- a/vxi11/version.py +++ b/vxi11/version.py @@ -1 +1 @@ -__version__ = '0.95' \ No newline at end of file +__version__ = '0.9'