#!/usr/local/bin/python
'''
소켓서버이면서 DB를 사용하는 예이다.
[볼만한 것]
1. ThreadingTCPServer 쓰는 법
2. ThreadingTCPServer2 클래스를 잘 봐라. 자꾸 binding에러가 나는 것을 막기위해 subclassing해서 allow_reuse_addr을 설정하여 binding에러가 안나게 했다. 이것 중요한 팁이다!!!
3. difftime 함수도 유용함. 두 시간사이의 간격을 초로 구한다.
4. DB쓰는 법도 봐라. DCOracle2를 썼다. commit을 불러줘야 반영되는 걸 잊지말고.
'''
import socket
from SocketServer import ThreadingTCPServer, StreamRequestHandler
import thread
import DCOracle2
import re
import time
PORT = 5030
conn_str = 'user/pass@service'
logpath = '/app/voce/mdc/MdcLog/viglog'
p_caller = re.compile(r'caller=(\d+)')
p_called = re.compile(r'called=(\d+)')
p_beg = re.compile(r'start=(\d+)-(\d+)')
p_end = re.compile(r'end=(\d+)-(\d+)')
def writelog(prefix, msg):
today = time.strftime('%Y%m%d')
logfilename = prefix + '.' + today
fp = open(logfilename, 'a')
fp.write(msg)
fp.close()
class ThreadingTCPServer2(ThreadingTCPServer):
def __init__(self, server_address, RequestHandlerClass):
self.allow_reuse_address = 1
ThreadingTCPServer.__init__(self, server_address, RequestHandlerClass)
class RequestHandler(StreamRequestHandler):
def handle(self):
sock = self.request
writelog(logpath, '### Connected ' + self.client_address[0] + '\n')
db = DCOracle2.connect(conn_str)
try:
data = self.recvline()
while data:
# begin
if data.startswith('quit'):
break
# log data
writelog(logpath, data)
# parse data
parsed = self.parse(data)
#print parsed
if len(parsed) == 5:
# insert db
cursor = db.cursor()
cursor.execute("INSERT INTO mdc_cdr VALUES('%s','%s',to_date('%s','YYYYMMDDHH24MISS'),to_date('%s','YYYYMMDDHH24MISS'),%d)" % ( parsed['caller'], parsed['called'], parsed['beg'], parsed['end'], (parsed['diff'] + 9)/10))
db.commit()
#print 'DB inserted'
# end
data = self.recvline()
except socket.error:
pass
db.close()
writelog(logpath, '### Disconnected ' + self.client_address[0] + '\n')
def recvline(self):
line = []
while True:
data = self.request.recv(1024)
line.append(data)
if data[-1] == '\n':
return ''.join(line)
def parse(self, data):
#print data.split()
#writelog(logpath, data.split()[1] + '\n')
if data.split()[1] <> 'END':
return {}
m_caller = p_caller.search(data)
m_called = p_called.search(data)
m_beg = p_beg.search(data)
m_end = p_end.search(data)
beg = m_beg.group(1)+m_beg.group(2)
end = m_end.group(1)+m_end.group(2)
return { 'caller':m_caller.group(1), 'called':m_called.group(1),
'beg':beg, 'end':end, 'diff':self.difftime(beg, end) }
def difftime(self, s1, s2):
t1 = time.mktime( (int(s1[:4]),int(s1[4:6]),int(s1[6:8]),int(s1[8:10]),int(s1[10:12]),int(s1[12:14]),0,0,0 ))
t2 = time.mktime( (int(s2[:4]),int(s2[4:6]),int(s2[6:8]),int(s2[8:10]),int(s2[10:12]),int(s2[12:14]),0,0,0 ))
return abs(int(t1) - int(t2))
if __name__ == '__main__':
server = ThreadingTCPServer2(("", PORT), RequestHandler)
server.allow_reuse_address = 1
server.serve_forever()
- TCPServer class를 상속받는 경우엔 TCPServer.allow_reuse_address = True로 바인딩 에러를 막을 수 있다.