今天对项目的各个已知BUG进行回溯,一个已经有一个月多的BUG终于有时间开始找原因。
写了二个测试程序,研究pyDES为何在我的项目中有时解密出来的数据是乱码,程序如下:
testServer.py
- #!/usr/bin/python
-
#-*- coding:utf-8-*-
-
-
import os,sys
-
import SocketServer,socket
-
import time,datetime
-
import base64
-
import pyDes
-
import threading,Queue
-
-
class MyServer(SocketServer.BaseRequestHandler):
-
def handle(self):
-
while True:
-
recvData = None
-
try:
-
recvData = self.request.recv(sockSize)
-
if not recvData:
-
time.sleep(1)
-
continue
-
recvData1 = _3ds.Decrypt(recvData)
-
userIp = str(self.client_address[0])
-
output = "recvData OK."
-
self.request.sendall(output)
-
tt = str(time.strftime('[%Y-%m-%d_%H:%M:%S]'))
-
writeLog(str(tt+"|decode="+recvData1)+"|"+userIp+"|recvData="+recvData)
-
except:
-
writeLog("recvData Error:"+userIp+str(sys.exc_info()[0])+str(sys.exc_info()[1]))
-
-
-
out = str(tt)+"recvData="+str(recvData)+"decode="+str(recvData1)
-
print out.decode("utf-8").encode("GBK")
-
-
class CLogInfo():
-
"""日志记录模块
-
"""
-
def __init__(self, logfile):
-
try:
-
import logging
-
self.logger = None
-
self.logger = logging.getLogger()
-
self.hdlr = logging.FileHandler(logfile)
-
formatter = logging.Formatter("[%(asctime)s] %(message)s", "%Y-%m-%d %H:%M:%S")
-
self.hdlr.setFormatter(formatter)
-
self.logger.addHandler(self.hdlr)
-
self.logger.setLevel(logging.DEBUG)
-
except:
-
##print "log init error!"
-
exit(1)
-
-
def output(self,logInfo,errFlag=0):
-
try:
-
if (errFlag):
-
##print "error:"+logInfo
-
self.logger.error("error:"+logInfo)
-
else:
-
##print logInfo
-
self.logger.info(logInfo)
-
except:
-
##print "log output error!"
-
exit(1)
-
-
def close(self):
-
try:
-
self.logger.removeHandler(self.hdlr)
-
except:
-
#print "log closed error!"
-
exit(1)
-
-
def writeLog(info):
-
"""记录日志方法
-
"""
-
try:
-
log.output(info)
-
-
except:
-
print "writeLog Error:"+str(sys.exc_info()[0])+str(sys.exc_info()[1])
-
pass
-
-
class _3DES():
-
"""加密模块
-
"""
-
def __init__(self):
-
self._3DES = pyDes.triple_des('0123456789012345', pyDes.CBC, '01234567', pad = None, padmode = pyDes.PAD_PKCS5)
-
def Encrypt(self,data):
-
e = self._3DES.encrypt(data)
-
return base64.b64encode(e)
-
-
def Decrypt(self,enData):
-
d = base64.b64decode(enData)
-
return self._3DES.decrypt(d)
-
-
-
-
if __name__ == "__main__":
-
sockSize = 640000
-
_3ds = _3DES()
-
global LOG,log
-
LOG = "c:\\testserver.log"
-
log = CLogInfo(LOG)
-
serverIP = "192.168.0.1"
-
port = "1111"
-
print "start..."
-
-
srv = SocketServer.ThreadingTCPServer((serverIP, int(port)),MyServer)
-
srv.serve_forever()
send.py,更简单,就是一个循环不停的发:
- #!/usr/bin/python
-
#-*- coding:utf-8-*-
-
-
import os,sys
-
import ConfigParser
-
import SocketServer,socket
-
import time,datetime
-
import base64
-
import pyDes
-
import threading,Queue
-
-
class _3DES():
-
"""加密模块
-
"""
-
def __init__(self):
-
self._3DES = pyDes.triple_des('0123456789012345', pyDes.CBC, '01234567', pad = None, padmode = pyDes.PAD_PKCS5)
-
def Encrypt(self,data):
-
e = self._3DES.encrypt(data)
-
return base64.b64encode(e)
-
-
def Decrypt(self,enData):
-
d = base64.b64decode(enData)
-
return self._3DES.decrypt(d)
-
-
def CommandRunThread(id,IP,PORT,sendCMD):
-
"""运行命令的线程模块
-
"""
-
try:
-
sock = getSock(IP, int(PORT))
-
sock.sendall(sendCMD)
-
TResponse = sock.recv(64000)
-
receiveData = str(IP) +": " + TResponse
-
sock.close()
-
except:
-
receiveData = str(IP) + ":Connect failed. 无法连接.\n"
-
#print receiveData[IP]
-
return receiveData
-
-
def getSock(host,port):
-
socket.setdefaulttimeout(10)
-
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-
sock.connect((host, port))
-
return sock
-
-
-
if __name__ == "__main__":
-
while True:
-
_3ds = _3DES()
-
cmd = '中文cmdcommand\3mv123325i2,中文测试'
-
cmd = _3ds.Encrypt(cmd)
-
result1 = CommandRunThread(id,'192.168.0.1','1111',cmd)
-
print result1.decode('utf-8').encode("gbk")
经过检查,发现当一对一的情况下,程序很正常,但是如果在不同的机器上各启动一个send.py,服务端就立即报错,收到的数据非常的妖异,部分字串解密成功,部分乱掉看都看不懂,我分析认为是pyDES在socketServer中无法下常使用的原因。只要改为base64就什么问题都没了。
目前无解中,如果一直找不到解决方案,只能放弃pyDES了。
不知道还有什么加解密方案可以用的。
2011年2月22日更新:
group.google上有人让我在纯多线程环境下写个测试来证明的确是多线程的问题,前个月杂事很多,一直没官,今天花了十分钟整了个测试程序,明确pyDES肯定在多线程下有问题的,我已经去邮件问pyDES的开发者的,看是否能有解决方案,目前我非常的困扰,我需要一个支持多线程的不受操作系统环境影响的加解密解决方案,速度能接受就行。如果实在不行,只能自己写个算法了,对自己写算法没有信心。
- #!/usr/bin/python
-
#-*- coding:utf-8-*-
-
import Queue, threading, sys, os
-
import time,urllib
-
import base64
-
import pyDes
-
-
# working thread
-
class Worker(threading.Thread):
-
worker_count = 0
-
def __init__( self, workQueue, resultQueue, timeout = 0, **kwds):
-
threading.Thread.__init__( self, **kwds )
-
self.id = Worker.worker_count
-
Worker.worker_count += 1
-
self.setDaemon( True )
-
self.workQueue = workQueue
-
self.resultQueue = resultQueue
-
self.timeout = timeout
-
self.start( )
-
-
def run( self ):
-
''' the get-some-work, do-some-work main loop of worker threads '''
-
while True:
-
try:
-
callable, args, kwds = self.workQueue.get(timeout=self.timeout)
-
res = callable(*args, **kwds)
-
print "worker[%2d]: %s" % (self.id, str(res) )
-
self.resultQueue.put( res )
-
except Queue.Empty:
-
break
-
except :
-
print 'worker[%2d]' % self.id, sys.exc_info()[:2]
-
-
class WorkerManager:
-
def __init__( self, num_of_workers=10, timeout = 1):
-
self.workQueue = Queue.Queue()
-
self.resultQueue = Queue.Queue()
-
self.workers = []
-
self.timeout = timeout
-
self._recruitThreads( num_of_workers )
-
-
def _recruitThreads( self, num_of_workers ):
-
for i in range( num_of_workers ):
-
worker = Worker( self.workQueue, self.resultQueue, self.timeout )
-
self.workers.append(worker)
-
-
def wait_for_complete( self):
-
# ...then, wait for each of them to terminate:
-
while len(self.workers):
-
worker = self.workers.pop()
-
worker.join( )
-
if worker.isAlive() and not self.workQueue.empty():
-
self.workers.append( worker )
-
print "All jobs are are completed."
-
-
def add_job( self, callable, *args, **kwds ):
-
self.workQueue.put( (callable, args, kwds) )
-
-
def get_result( self, *args, **kwds ):
-
return self.resultQueue.get( *args, **kwds )
-
-
-
-
def test_job(id, sleep = 0.001 ):
-
try:
-
result = _3ds.Encrypt("hello")
-
#result = base64.b64encode("HELLO")
-
print id, result
-
except:
-
print '[%4d]' % id, sys.exc_info()[:2]
-
return id
-
-
def test():
-
import socket
-
socket.setdefaulttimeout(10)
-
print 'start testing'
-
wm = WorkerManager(10)
-
for i in range(100):
-
wm.add_job( test_job, i, i*0.001 )
-
wm.wait_for_complete()
-
print 'end testing'
-
-
class _3DES():
-
"""加密模块
-
"""
-
def __init__(self):
-
self._3DES = pyDes.triple_des('0123456789012345', pyDes.CBC, '01234567', pad = None, padmode = pyDes.PAD_PKCS5)
-
def Encrypt(self,data):
-
e = self._3DES.encrypt(data)
-
return base64.b64encode(e)
-
-
def Decrypt(self,enData):
-
d = base64.b64decode(enData)
-
return self._3DES.decrypt(d)
-
-
-
if __name__ == '__main__':
-
_3ds = _3DES()
-
test()
执行以上程序,程序抛出大量乱七八糟的异常,但只要改成base64,什么问题都没了。
2月22日第二次更新:
我得到了作者的回复,pyDES不是线程安全的。。。如果要在线程中使用,需要为每一个线程准备一个实例。。。。
所以,无解了,准备自己的加解密算法吧,先翻书去了。
阅读(1893) | 评论(2) | 转发(1) |