2014-02-17 17 views
0

我試圖用SSL編程最簡單的客戶端 - 服務器應用程序,我遇到以下問題:
1)如何減少序列化的時間JSON?
2)也許有什麼比LineReciver更好的存在,用於創建服務器和客戶端之間的通信?或者我可以增加接收的行數?在Twisted中形成的響應時間太長(self.transport.write)

的源代碼:
一)ServerSLL

import server 
from twisted.internet.protocol import Factory 
from twisted.internet import reactor 
from OpenSSL import SSL 

class ServerSSL(object): 
    def getContext(self): 
     ctx = SSL.Context(SSL.SSLv23_METHOD) 
     ctx.use_certificate_file('server_cert.pem') 
     ctx.use_privatekey_file('server_key.pem') 
     return ctx 


if __name__ == '__main__': 
    factory = Factory() 
    factory.protocol = server.Server 
    reactor.listenSSL(8000, factory, ServerSSL()) 
    reactor.run() 

B)服務器

from json import dumps, loads 
import sqlalchemy 
from sqlalchemy.orm import sessionmaker 
from db.create_db import Users 
from twisted.internet.protocol import Protocol, Factory 
from twisted.internet import reactor 

engine = sqlalchemy.create_engine('postgresql://user:[email protected]/csan', pool_size=20, max_overflow=0) 


class Server(Protocol): 
    def __init__(self): 
     self.Session = sessionmaker(bind=engine) 

    def __del__(self): 
     self.session.close() 

    def authorization(self, data): 
     """ 
      Checking user with DB 
     """ 
     session = self.Session() 
     result = session.execute(sqlalchemy.select([Users]).where(Users.name == data['user'])) 
     result = result.fetchone() 
     if result is None: 
      data['error'] = 404 
     else: 
      if result['name'] == data['user']: 
       # correct users info --> real user 
       if result['password'] == data['pswd']: 
        data['auth'] = 1 
       # incorrect password --> fake user 
       else: 
        data['error'] = 403 
     session.close() 
     return data 

    def dataReceived(self, data): 
     """ 
      Processing request from user and send response 
     """ 
     new_data = loads(data) 
     if new_data['cmd'] == 'AUTH': 
      response = self.authorization(new_data) 
     self.transport.write(str(dumps(new_data))) 


if __name__ == '__main__': 
    f = Factory() 
    f.protocol = Server 
    reactor.listenTCP(8000, f) 
    reactor.run() 

C)client_console

from json import dumps, loads 
from twisted.internet.protocol import ClientFactory 
from twisted.protocols.basic import LineReceiver 
from twisted.internet import ssl, reactor 

class ServerClientSSL(LineReceiver): 
    """ 
     Basic client for talking with server under SSL 
    """ 

    def connectionMade(self): 
     """ 
     Send auth request to serverSLL.py 
     """ 
     login = raw_input('Login:') 
     password = raw_input('Password:') 
     hash_password = str(hash(password)) 
     data = dumps({'cmd': 'AUTH', 'user': login, 'pswd': hash_password, 'auth': 0, 'error': 0}) 
     self.sendLine(str(data)) 

    def connectionLost(self, reason): 
     """ 
      Says to client, why we are close connection 
     """ 
     print 'connection lost (protocol)' 

    def lineReceived(self, data): 
     """ 
      Processing responses from serverSSL.py and send new requests to there 
     """ 
     new_data = loads(data) 
     if new_data['cmd'] == 'BBYE': 
      self.transport.loseConnection() 
     else: 
      print new_data 


class ServerClientSLLFactory(ClientFactory): 
    protocol = ServerClientSSL 

    def clientConnectionFailed(self, connector, reason): 
     print 'connection failed:', reason.getErrorMessage() 
     reactor.stop() 

    def clientConnectionLost(self, connector, reason): 
     print 'connection lost:', reason.getErrorMessage() 
     reactor.stop() 

if __name__ == '__main__': 
    import sys 
    if len(sys.argv) < 3: 
     print 'Using: python client_console.py [IP] [PORT] ' 
    else: 
     ip = sys.argv[1] 
     port = sys.argv[2] 
     factory = ServerClientSLLFactory() 
     reactor.connectSSL(ip, int(port), factory, ssl.ClientContextFactory()) 
     reactor.run() 

回答

1
class ServerSSL(object): 
    ... 

不要寫自己的C ontext工廠。改爲使用twisted.internet.ssl.CertificateOptions。它比你在這裏有更少的問題。

def __del__(self): 
    self.session.close() 

__del__第一條規則:不要使用__del__。添加此方法不會爲您提供自動會話清理。相反,它幾乎可以確保您的會話永遠不會被清理。協議有一個方法在完成時被調用 - 它被稱爲connectionLost。改爲使用它。

result = session.execute(sqlalchemy.select([Users]).where(Users.name == data['user'])) 
result = result.fetchone() 

Twisted是一個單線程多任務系統。這些語句阻塞網絡I/O和數據庫操作。當他們運行你的服務器時沒有做其他事情。

使用twisted.enterprise.adbapitwext.enterprise.adbapi2alchimia來代替異步執行數據庫交互。

class ServerClientSSL(LineReceiver): 
    ... 

有很多協議比LineReceiver更好。你可以做的最簡單的改進是切換到Int32StringReceiver。更大幅度的改進將是切換到twisted.protocols.amp

1)如何減少JSON序列化的時間?

使用更快的JSON庫。但是,在修復應用程序中的阻塞數據庫代碼後,我懷疑你仍然需要更快的JSON庫。

2)也許有什麼比LineReciver更好的存在,用於創建服務器和客戶端之間的通信?或者我可以增加接收的行數?

LineReceiver.MAX_LENGTH。當你切換到Int32StringReceiverAMP你不會再需要這個了。