问题:modbus_tk开发中遇到[Errno 98] Address already in use (已解决)
案例:
1 from modbus_tk import modbus_tcp,defines 2 import time 3 4 s = modbus_tcp.TcpServer(port=5300) 5 6 def main(): 7 try: 8 s.start() 9 s.add_slave(1) 10 sl = s.get_slave(1) 11 sl.add_block('block0',defines.HOLDING_REGISTERS,0,100) 12 sl.set_values('block0',0,[1 for i in range(10)]+[2 for i in range(10)]+[3 for i in range(10)]) 13 print('pre stop') 14 except: 15 print('error') 16 finally: 17 time.sleep(10) 18 s.stop() 19 print('stop') 20 21 if __name__ == "__main__": 22 main()
程序中,首先创建了一个端口为5003的modbus_tcp slave服务器,执行start()后,服务器启动。
然后,在此 server 上创建了一个 id 为1的 slave 节点。
在此 slave 节点上创建一个地址为0~100的 (HOLDING_REGISTERS) 保持寄存器块。
在 block0 这个寄存器块上设置值。
实验结果如下图:

然后再次执行 python3 t.py 却提示 Address already in use.

🤔考虑是由于端口被占用导致的,于是使用之前文章《基于Python的检测端口是否在使用》的方法查看端口:
修改代码如下:
1 from modbus_tk import modbus_tcp,defines 2 import socket 3 4 s = modbus_tcp.TcpServer(port=5003) 5 6 def net_is_used(port,ip='127.0.0.1'): 7 s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 8 try: 9 s.connect((ip,port)) 10 s.shutdown(2) 11 print('%s:%d is used' % (ip,port)) 12 return True 13 except: 14 print('%s:%d is unused' % (ip,port)) 15 return False 16 17 def main(): 18 global s 19 try: 20 a = s.start() 21 s.add_slave(3) 22 sl = s.get_slave(3) 23 sl.add_block('block0',defines.HOLDING_REGISTERS,0,100) 24 sl.set_values('block0',0,[1 for i in range(10)]+[2 for i in range(10)]+[3 for i in range(10)]) 25 # a = s.start() 26 print(a) 27 print('pre stop') 28 except: 29 print('error') 30 finally: 31 net_is_used(5003) 32 import time 33 time.sleep(10) 34 while 1: 35 pass 36 s.stop() 37 print('stop') 38 39 if __name__ == "__main__": 40 main()
结果:

1 pi@raspberry:~/Desktop $ pip3 show modbus_tk 2 Name: modbus-tk 3 Version: 0.5.8 4 Summary: Implementation of modbus protocol in python 5 Home-page: https://github.com/ljean/modbus-tk/ 6 Author: Luc Jean 7 Author-email: luc.jean@gmail.com 8 License: LGPL 9 Location: /home/pi/.local/lib/python3.5/site-packages 10 Requires: pyserial
1 def _do_init(self): 2 """initialize server""" 3 self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 4 self._sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1) 5 if self._timeout_in_sec: 6 self._sock.settimeout(self._timeout_in_sec) 7 self._sock.setblocking(0) 8 self._sock.bind(self._sa) 9 self._sock.listen(10) 10 self._sockets.append(self._sock)

百思不得其解。究竟为什么会这样呢?
最后查看Issue 发现也有人遇到相似的问题。
[Errno 98] Address already in use · Issue #82 · ljean/modbus-tk · GitHub
https://github.com/ljean/modbus-tk/issues/82
setsockopt 设置socket 详细用法 - youxiazzz12的专栏 - CSDN博客
https://blog.csdn.net/youxiazzz12/article/details/25634143
setsockopt中参数之SO_REUSEADDR的意义 - chenlycly的专栏 - CSDN博客
https://blog.csdn.net/chenlycly/article/details/52191441
浙公网安备 33010602011771号