socketIO 관련 프로젝트를 하면서 NodeJS를 처음부터 사용할 생각은 아니었지만
어쩌다가 Flask를 이용한 socketIO를 사용하게 되어 간단한 구조를 살펴보고 제가 작성한 코드를
올리려고 합니다.
우선 이 Flask socketIO란 놈은 구버전 익스플로러같은 곳에서는 수신이 안될 수 있으니 주의하시기 바랍니다.
저도 그것때문에 NodeJS socketIO로 바꿨습니다. 그것 빼고는 아주 무난하게 동작합니다.
from flask import Flask, render_template from flask_socketio import SocketIO, emit
우선 해당 라이브러리들을 임포트해줍니다.
그리고 플라스크 socketIO 객체를 생성합니다.
app = Flask(__name__) app.config['SECRET_KEY'] = 'secret!' socketio = SocketIO(app)
그리고 밑에 코드는 써도 좋고 안써도 좋습니다. 결과를 관찰하기 위해 html 템플릿을 렌더시킨 것이기 때문입니다.
@app.route('/') def index(): return render_template('data.html')
그리고 run을 시켜주면 되는데요.
global app socketio.run(app, host='0.0.0.0', port=5555)
저는 포트넘버를 5555로 잡았습니다.
그리고 간단한 수신부 코드를 만들어 보았습니다. 수신부 명을 ‘real_time’ 이라고 임의로 지어 주고, send_data라는 함수명은 아무렇게 지어줘도 상관없습니다.
그리고 함수명 옆에 message라는 파라미터는 발신부에서 보내주는 데이터를 받아올 수 있는 파라미터입니다.
@socketio.on('real_time') def send_data(message): from datetime import datetime global timecheck global result try: now = str(datetime.utcnow().replace(microsecond=0)) if timecheck == now: emit('fromserver', json.dumps({'data': result['data']})) else: get = {"time": now} result = db["buffer"].find_one(get) emit('fromserver', json.dumps({'data': result['data']})) timecheck = now # exception handling except: # db.close() print("occur exeption" + format_exc())
저는 수신부와 연결된 모든 클라이언트에게 전송할 것이기 때문에 emit함수를 사용하였는데요, 사용 목적에 따라 함수 선택 해주시면 됩니다.
자세한 설명은 flask-socketIO 문서를 참고하세요.
이 단락의 코드를 간단히 설명하자면 ‘real_time’ 이라는 수신부로 받은 소켓데이터에서 message 파라미터는 이용하지 않았지만 현재 시간을 기준으로 db[“buffer”]에 있는 데이터를 얻어 json으로 파싱하여 모든 클라이언트에 전송하는 로직의 코드입니다.
풀 소스코드는 아래에 첨부하였습니다.
# -*- coding: utf8 -*- import multiprocessing import pandas as pd from pandas.tseries.offsets import Hour, Minute, Second import json from traceback import format_exc from pymongo import MongoClient client = MongoClient('localhost', 27017) db = client['seismic'] timecheck = "" result = [] from flask import Flask, render_template from flask_socketio import SocketIO, emit app = Flask(__name__) app.config['SECRET_KEY'] = 'secret!' socketio = SocketIO(app) @app.route('/') def index(): return render_template('data.html') class IO_Socket(multiprocessing.Process): """client connection generator""" def __init__(self): """ constructor for multiprocessing """ multiprocessing.Process.__init__(self) self.__suspend = False self.__exit = False def run(self): """Process start method""" # wrap Flask application with socketio's middleware global app socketio.run(app, host='0.0.0.0', port=5555) def mySuspend(self): self.__suspend = True def myResume(self): self.__suspend = False def myExit(self): self.__exit = True @socketio.on('real_time') def send_data(message): from datetime import datetime global timecheck global result try: now = str(datetime.utcnow().replace(microsecond=0) + Hour(9) - Second(5)) if timecheck == now: emit('fromserver', json.dumps({'data': result['data']})) else: get = {"time": now} result = db["buffer"].find_one(get) emit('fromserver', json.dumps({'data': result['data']})) timecheck = now # exception handling except: # db.close() print("occur exeption" + format_exc()) # pass # else: # print('off mode') # pass # else: # send_by_time(message)
전체 코드 중에서 몽고 디비를 같이 쓰긴 했지만 쓰시는 목적에 따라 코드 변경해 주시면 됩니다.