การทำ Message Server เพื่อตรวจสอบสถานะของเครื่อง Server


แนวคิด
จะมี Message Server ที่เป็น main server ให้ client ส่งข้อมูล  ผ่าน network เข้ามา
  HOST client 1, 2  3 ... 80 =====> Message Server

ให้คิดเหมือนส่งข้อมูลมารายงานตัวทุกๆ ชั่วโมง ในช่วงต้นชั่วโมง และ Message Server จะทำการเก็บข้อมูลลงใน   directory แยกตามวัน  โดยสร้างชื่อแฟ้มเพื่อบ่งว่าเป็นการรายงานจาก client host ใด ของช่วงเวลาใด

ในช่วง 5 นาทีหลังจากนั้น server จะมี โปรแกรมมาอ่านแฟ้ม
  • ตรวจว่าเครื่องไหนไม่รายงานแสดงว่ามีปัญหา  จะส่ง message ไปที่ Line Group ว่า client ใดที่ไม่รายงานตัว
  • กรณีรายงานตัว จะนำข้อมูลนั้นมาดูว่ามีปัญหาหรือไม่ ถ้ามีปัญหาจะส่ง message ไปที่ Line Group ว่า client นั้นมีปัญหา
  • ทำการเก็บข้อมูลนั้นลงใน database server


ดังนั้นโปรแกมในฝั่ง server จะมี 2 ตัวคือ
 1. Daemon ที่คอยรับข้อมูลจาก client เพื่อเขียนลงแฟ้ม
 2. เป็น Cron tab โปรแกรมที่ทำงานทุกประมาณ 5 นาที

ส่วนฝั่ง Client จะมีโปรแกรมเดียว คอยส่งรายงานให้กับ server


ข้อกำหนดของ Server Daemon
 ทำการสร้าง  Socket ,  Bind  Socket  
 วน Loop เพื่อเป็น ​Daemon
   รอรับ Connection  และข้อมูล จาก  Client
   ทำการ decrypt ข้อมูลที่เข้ารหัส
   ทำการสร้างแฟ้มข้อมูลด้วยชื่อที่ตกลงไว้ลงใน directory ตามวันที่

ข้อกำหนดของ Server Cron tab โปรแกรม
 ทำการอ่านข้อมูลจากแฟ้มตามช่วงเวลา
 ถ้าไม่พบการรายงานตัวของ Host client ใดทำการส่งข้อมูลไปยัง Line group
 อ่านแฟ้มข้อมูล ถ้าพบปัญหาทำการ ส่งข้อมูลไปยัง Line group
 นำข้อมูลลงไปเก็บไว้ใน database server


ข้อกำหนดของ Client Cron tab โปรแกรม
 ทำการสร้าง  Socket ,  Bind  Socket  
 อ่านสถานภาพของเครื่องตามข้อกำหนด
 ทำการ encrypt ข้อมูล

 ทำการส่วข้อมูลใน Server


ทดลองสร้าง Socket client เพื่อต่อเชื่อมกับ web server และอ่าน web page กลับมา
client01.py

1

2
3
4
5
6
7
8
9
10
11
12
13
14
import socket

#HOST = 'www.google.com'
IP = '61.19.2.168'
PORT = 80
BUFFER_SIZE = 2048
ADDRESS = ( HOST , IP )

client = socket.socket( socket.AF_INET , socket.SOCK_STREAM )
client.connect( ADDRESS )

message = "GET / HTTP/1.1\r\n\r\n"
client.sendall( message )
data = client.recv( BUFFER_SIZE)
print data

3.  ip ของ www.google.com
8. ทำการสร้าง socket ที่เป็นแบบเชื่อมกับ internet และเป็น stream ( TCP )
9. ทำการเชื่อมกับ web server ตาม IP และ PORT ทำกำหนด
12. ส่ง request ตามมาตรฐานของ HTTP request
13. ทำการรับข้อมูลที่ web server ส่งกลับมา


client02.py


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# -*- coding: utf-8 -*-

import socket
import sys

# 1. สร้าง socket
try:
   client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error:
   print 'Failed to create socket'
   sys.exit()
print 'Socket Created'

# 2. Get IP จาก host name
HOST = 'www.google.com';
try:
   IP = socket.gethostbyname( HOST )
except socket.gaierror:
   #could not resolve
   print 'Hostname could not be resolved. Exiting'
   sys.exit()

# 3.Connect to remote server
PORT = 80
ADDRESS = ( IP , PORT )
client.connect( ADDRESS )
print 'Socket Connected to ' + HOST + ' on ip ' + IP

# 4.Send some data to remote server
message = "GET / HTTP/1.1\r\n\r\n"
try :
   #Set the whole string
   client.sendall(message)
except socket.error:
   #Send failed
   print 'Send failed'
   sys.exit()
print 'Message send successfully'

# 5.Now receive data
BUFFER_SIZE = 2048
client.sendall( message )
data = client.recv( BUFFER_SIZE)
print data

การสร้าง Message Server และ Client
server03.py
ส่วนของ Server daemon

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import socket
import time

IP = '127.0.0.1'
PORT = 12345
BUFFER_SIZE = 2048
ADDRESS = ( IP, PORT )

serverSocket = socket.socket( socket.AF_INET , socket.SOCK_STREAM)
serverSocket.bind( ADDRESS )
serverSocket.listen( 5 )

while True :
   print "waiting for connection ..."
   clientSocket , address = serverSocket.accept()
   print "Connection from " , address
   clientData = clientSocket.recv( BUFFER_SIZE)
   print "Data from client " , clientData
   print "Send data to client =>"
   clientSocket.send("[%s]" % (time.ctime() ))
   clientSocket.close()

serverSocket.close()


9. สร้าง socket
10. ทำการ bind กับ IP  และ PORT
13. เป็นการทำ loop ที่วนตลอด
15. เป็นการรอ client ที่จะ connect เข้ามา  โปรแกรมจะหยุดที่บรรทัดนี้จนกว่าจะมี connection เข้ามา
17. เป็นการรับข้อมูลที่ client ส่งมา
20. เป็นการส่งข้อมูลกลับไปที่ client

ส่วนของ client ที่จะ connect ไปยัง server

client03.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import socket

IP = '127.0.0.1'
PORT = 12345
BUFFER_SIZE = 2048
ADDRESS = ( IP, PORT )

clientSocket = socket.socket( socket.AF_INET , socket.SOCK_STREAM)
clientSocket.connect( ADDRESS )


data = raw_input("Please enter data >")
clientSocket.send( data )
serverData = clientSocket.recv( BUFFER_SIZE)
print serverData

clientSocket.close()


การทดลองแปลงข้อมูลเป็น JSON ทางฝั่ง client

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

import socket
import json

IP = '127.0.0.1'
PORT = 12345
BUFFER_SIZE = 2048
ADDRESS = ( IP, PORT )

clientSocket = socket.socket( socket.AF_INET , socket.SOCK_STREAM)
clientSocket.connect( ADDRESS )


#data = raw_input("Please enter data >")
data = { "hostname" : 'server01' , "memory" : 9 , "load" : 30}
jsonData = json.dumps( data )
clientSocket.send( jsonData )
serverData = clientSocket.recv( BUFFER_SIZE)
print serverData

clientSocket.close()


15. แปลงข้อมูลที่เป็น record ให้เป็น JSON string เพื่อส่งผ่าน network ได้

การรับข้อมูล JSON ฝั่ง client แล้วแปลง

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import socket
import time
import json

IP = '127.0.0.1'
PORT = 12345
BUFFER_SIZE = 2048
ADDRESS = ( IP, PORT )

serverSocket = socket.socket( socket.AF_INET , socket.SOCK_STREAM)
serverSocket.bind( ADDRESS )
serverSocket.listen( 5 )

while True :
   print "waiting for connection ..."
   clientSocket , address = serverSocket.accept()
   print "Connection from " , address
   clientData = clientSocket.recv( BUFFER_SIZE)
   data  = json.loads( clientData )
   print "Data from client " , clientData
   print "Send data to client =>"
   clientSocket.send("[%s]" % (time.ctime() ))
   clientSocket.close()

serverSocket.close()

19. แปลง string ให้เป็น record

การ encry ใช้ library จาก http://docs.python-guide.org/en/latest/scenarios/crypto/


ต้อง install ด้วยคำสั่ง -> pip install cryptography

ส่วนของ client  ที่มีการ encrypt ข้อมูล
client05.py


import socket
import json
#--------------- Section ENCEYPTION ----------------------------
# From http://stackoverflow.com/questions/12524994/encrypt-decrypt-using-pycrypto-aes-256
BS = 16
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
unpad = lambda s : s[:-ord(s[len(s)-1:])]
#
import base64
from Crypto.Cipher import AES
from Crypto import Random
#
class AESCipher:
   def __init__( self, key ):
       self.key = key
   def encrypt( self, raw ):
       raw = pad(raw)
       iv = Random.new().read( AES.block_size )
       cipher = AES.new( self.key, AES.MODE_CBC, iv )
       return base64.b64encode( iv + cipher.encrypt( raw ) )
   def decrypt( self, enc ):
       enc = base64.b64decode(enc)
       iv = enc[:16]
       cipher = AES.new(self.key, AES.MODE_CBC, iv )
       return unpad(cipher.decrypt( enc[16:] ))
#--------------- Section ENCEYPTION ----------------------------
# key must be 16 * x
engine = AESCipher( '1234567890123456')

IP = '127.0.0.1'
PORT = 12345
BUFFER_SIZE = 2048
ADDRESS = ( IP, PORT )

clientSocket = socket.socket( socket.AF_INET , socket.SOCK_STREAM)
clientSocket.connect( ADDRESS )


#data = raw_input("Please enter data >")
data = { "hostname" : 'server01' , "memory" : 9 , "load" : 30}
jsonData = json.dumps( data )
encryptData = engine.encrypt( jsonData )
clientSocket.send( encryptData )
serverData = clientSocket.recv( BUFFER_SIZE)
print serverData

clientSocket.close()


ส่วนของ server ที่มีการ decrypt ข้อมูล

server05.py


import socket
import time
import json

from Crypto import Random
from Crypto.Cipher import AES
import base64

#--------------- Section ENCEYPTION ----------------------------
# From http://stackoverflow.com/questions/12524994/encrypt-decrypt-using-pycrypto-aes-256
BS = 16
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
unpad = lambda s : s[:-ord(s[len(s)-1:])]

import base64
from Crypto.Cipher import AES
from Crypto import Random

class AESCipher:
   def __init__( self, key ):
       self.key = key

   def encrypt( self, raw ):
       raw = pad(raw)
       iv = Random.new().read( AES.block_size )
       cipher = AES.new( self.key, AES.MODE_CBC, iv )
       return base64.b64encode( iv + cipher.encrypt( raw ) )

   def decrypt( self, enc ):
       enc = base64.b64decode(enc)
       iv = enc[:16]
       cipher = AES.new(self.key, AES.MODE_CBC, iv )
       return unpad(cipher.decrypt( enc[16:] ))
#--------------- Section ENCEYPTION ----------------------------
# key must be 16 * x
engine = AESCipher( '1234567890123456')

IP = '127.0.0.1'
PORT = 12345
BUFFER_SIZE = 2048
ADDRESS = ( IP, PORT )

serverSocket = socket.socket( socket.AF_INET , socket.SOCK_STREAM)
serverSocket.bind( ADDRESS )
serverSocket.listen( 5 )

while True :
   print "waiting for connection ..."
   clientSocket , address = serverSocket.accept()
   print "Connection from " , address
   clientData = clientSocket.recv( BUFFER_SIZE)
   clientData = engine.decrypt( clientData )
   data  = json.loads( clientData )
   print "Data from client " , data
   print "Send data to client =>"

   clientSocket.send("[%s]" % (time.ctime() ))
   clientSocket.close()

serverSocket.close()


ความคิดเห็น

โพสต์ยอดนิยมจากบล็อกนี้

แจ้งเตือนเข้าไลน์กลุ่ม ผ่าน Line notify เมื่อมีคน login เข้า server ของเราผ่าน SSH (linux) หรือ remote desktop เข้ามา (windows server)

การทำ cloud iot ด้วย thingsboard ไว้ใช้เองครับ

การประยุกต์ใช้ line notify ในการแจ้งปัญหาการใช้งาน สำหรับ php