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()后,服务器启动。html
而后,在此 server 上建立了一个 id 为1的 slave 节点。python
在此 slave 节点上建立一个地址为0~100的 (HOLDING_REGISTERS) 保持寄存器块。git
在 block0 这个寄存器块上设置值。github
实验结果以下图:服务器
而后再次执行 python3 t.py 却提示 Address already in use.app
🤔考虑是因为端口被占用致使的,因而使用以前文章《基于Python的检测端口是否在使用》的方法查看端口:socket
修改代码以下:tcp
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()
结果:ide
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)
百思不得其解。究竟为何会这样呢?ui
最后查看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