歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Python 用心跳(UDP包)探測不活動主機

Python 用心跳(UDP包)探測不活動主機

日期:2017/3/1 10:07:33   编辑:Linux編程

計算機周期性的發送一個代表心跳的UDP包到服務器,服務器跟蹤每台計算機在上次發送心跳之後盡力的時間並報告那些沉默時間太長的計算機。

客戶端程序:HeartbeatClient.py

  1. """ 心跳客戶端,周期性的發送 UDP包 """
  2. import socket, time
  3. SERVER_IP = '192.168.0.15'; SERVER_PORT = 43278; BEAT_PERIOD = 5
  4. print'Sending heartbeat to IP %s , port %d' % (SERVER_IP, SERVER_PORT)
  5. print'press Ctrl-C to stop'
  6. whileTrue:
  7. hbSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  8. hbSocket.sendto('PyHB', (SERVER_IP, SERVER_PORT))
  9. if _ _debug_ _:
  10. print'Time: %s' % time.ctime( )
  11. time.sleep(BEAT_PERIOD)

服務器程序接受ing跟蹤“心跳”,她運行的計算機的地址必須和“客戶端”程序中的 SERVER_IP一致。服務器必須支持並發,因為來自不同的計算機的心跳可能會同時到達。一個服務器有兩種方法支持並發:多線程和異步操作。下面是一個多線程的ThreadbearServer.py,只使用了python標准庫中的模塊:

  1. """ 多線程 heartbeat 服務器"""
  2. import socket, threading, time
  3. UDP_PORT = 43278; CHECK_PERIOD = 20; CHECK_TIMEOUT = 15
  4. class Heartbeats(dict):
  5. """ Manage shared heartbeats dictionary with thread locking """
  6. def _ _init_ _(self):
  7. super(Heartbeats, self)._ _init_ _( )
  8. self._lock = threading.Lock( )
  9. def _ _setitem_ _(self, key, value):
  10. """ Create or update the dictionary entry for a client """
  11. self._lock.acquire( )
  12. try:
  13. super(Heartbeats, self)._ _setitem_ _(key, value)
  14. finally:
  15. self._lock.release( )
  16. def getSilent(self):
  17. """ Return a list of clients with heartbeat older than CHECK_TIMEOUT """
  18. limit = time.time( ) - CHECK_TIMEOUT
  19. self._lock.acquire( )
  20. try:
  21. silent = [ip for (ip, ipTime) inself.items( ) if ipTime < limit]
  22. finally:
  23. self._lock.release( )
  24. return silent
  25. class Receiver(threading.Thread):
  26. """ Receive UDP packets and log them in the heartbeats dictionary """
  27. def _ _init_ _(self, goOnEvent, heartbeats):
  28. super(Receiver, self)._ _init_ _( )
  29. self.goOnEvent = goOnEvent
  30. self.heartbeats = heartbeats
  31. self.recSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  32. self.recSocket.settimeout(CHECK_TIMEOUT)
  33. self.recSocket.bind(('', UDP_PORT))
  34. def run(self):
  35. whileself.goOnEvent.isSet( ):
  36. try:
  37. data, addr = self.recSocket.recvfrom(5)
  38. if data == 'PyHB':
  39. self.heartbeats[addr[0]] = time.time( )
  40. except socket.timeout:
  41. pass
  42. def main(num_receivers=3):
  43. receiverEvent = threading.Event( )
  44. receiverEvent.set( )
  45. heartbeats = Heartbeats( )
  46. receivers = [ ]
  47. for i in range(num_receivers):
  48. receiver = Receiver(goOnEvent=receiverEvent, heartbeats=heartbeats)
  49. receiver.start( )
  50. receivers.append(receiver)
  51. print'Threaded heartbeat server listening on port %d' % UDP_PORT
  52. print'press Ctrl-C to stop'
  53. try:
  54. whileTrue:
  55. silent = heartbeats.getSilent( )
  56. print'Silent clients: %s' % silent
  57. time.sleep(CHECK_PERIOD)
  58. except KeyboardInterrupt:
  59. print'Exiting, please wait...'
  60. receiverEvent.clear( )
  61. for receiver in receivers:
  62. receiver.join( )
  63. print'Finished.'
  64. if _ _name_ _ == '_ _main_ _':
  65. main( )

作為備選方案,線面給出異步的AsyBeatserver.py程序,這個程序接住了強大的twisted的力量:

  1. import time
  2. from twisted.application import internet, service
  3. from twisted.internet import protocol
  4. from twisted.python import log
  5. UDP_PORT = 43278; CHECK_PERIOD = 20; CHECK_TIMEOUT = 15
  6. class Receiver(protocol.DatagramProtocol):
  7. """ Receive UDP packets and log them in the "client"s dictionary """
  8. def datagramReceived(self, data, (ip, port)):
  9. if data == 'PyHB':
  10. self.callback(ip)
  11. class DetectorService(internet.TimerService):
  12. """ Detect clients not sending heartbeats for too long """
  13. def _ _init_ _(self):
  14. internet.TimerService._ _init_ _(self, CHECK_PERIOD, self.detect)
  15. self.beats = { }
  16. def update(self, ip):
  17. self.beats[ip] = time.time( )
  18. def detect(self):
  19. """ Log a list of clients with heartbeat older than CHECK_TIMEOUT """
  20. limit = time.time( ) - CHECK_TIMEOUT
  21. silent = [ip for (ip, ipTime) inself.beats.items( ) if ipTime < limit]
  22. log.msg('Silent clients: %s' % silent)
  23. application = service.Application('Heartbeat')
  24. # define and link the silent clients' detector service
  25. detectorSvc = DetectorService( )
  26. detectorSvc.setServiceParent(application)
  27. # create an instance of the Receiver protocol, and give it the callback
  28. receiver = Receiver( )
  29. receiver.callback = detectorSvc.update
  30. # define and link the UDP server service, passing the receiver in
  31. udpServer = internet.UDPServer(UDP_PORT, receiver)
  32. udpServer.setServiceParent(application)
  33. # each service is started automatically by Twisted at launch time
  34. log.msg('Asynchronous heartbeat server listening on port %d\n'
  35. 'press Ctrl-C to stop\n' % UDP_PORT)
Copyright © Linux教程網 All Rights Reserved