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