Thrift遠程通信教程

Thrift遠程通信教程

目標:實現Python通過Thrift實現服務器-客戶端相互通信。

前期準備

  • thrift.exe可執行文件
  • 官方.thrift樣例文件
    在這裏插入圖片描述

無加密本地通信版本

修改.thrift文件

如圖所示:
在這裏插入圖片描述

利用thrift腳本創建gen-py文件夾

在當前目錄打開一個命令行工具:
在這裏插入圖片描述
在命令行工具裏敲入以下命令:

.\thrift -r --gen py ./tutorial.thrift

其中.\thrift是打開當前目錄下的名字叫thrift的程序,後面是參數。

通過直接打開的方式可以省去配置環境變量的過程。

安裝python的thrift庫

在任意目錄下的命令行工具裏敲入以下命令即可安裝:

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple thrift

有的同學的電腦安裝到一半可能會斷掉,這是因爲訪問外網太慢導致的,可以多執行幾次,只要有一次安裝成功即可。

修改PythonServer.py文件

在原來什麼都不動的情況下,在CalculatorHandler 末尾加入一個剛纔定義好的函數,進行這個函數的實現方法。

def echo(self, msg, cnt):
	print("%s,%d"%(msg,cnt))
	return cnt + 1

在這裏插入圖片描述

修改PythonClient.py文件

在PythonClient.py 中添加如下代碼

flag=client.echo("hello server!",2020)
print("hello server!,%d"%flag)

在這裏插入圖片描述

運行

先運行Server端,再運行Client端。
在這裏插入圖片描述
在這裏插入圖片描述

加密本地通信版本

前期準備

相較於無加密版本需要有openssl軟件來生成密鑰和證書。
在這裏插入圖片描述

安裝openssl

在這裏插入圖片描述
在這裏插入圖片描述
注意,此處安裝目錄爲C:\OpenSSL-Win64
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

測試openssl

打開命令行工具,輸入:

C:\OpenSSL-Win64\bin\openssl version

在這裏插入圖片描述
如果出現版本號就說明配置成功。

生成私鑰和證書

  1. 在你想要存放密鑰和證書的目錄下打開命令行,輸入如下命令
C:\OpenSSL-Win64\bin\openssl req -new -x509 -days 365 -nodes -out cert.pem -keyout key.pem
  1. 國家輸入CN在這裏插入圖片描述
  2. 不重要的可以不填,直接按回車即可跳過。
  3. 到服務器這一個的時候填入本機地址:127.0.0.1在這裏插入圖片描述
  4. 剩下的繼續回車跳過。
  5. 可以看到目錄下已經有了私鑰和證書,其中"cert.pem"是客戶端用的公鑰(證書),"key.pem"是服務器用的私鑰。在這裏插入圖片描述

修改python文件,使用證書加密通信

利用thrift生成gen-py文件夾:
在這裏插入圖片描述

Server端:

在這裏插入圖片描述
在這裏插入圖片描述
將1處的代碼修改爲

from thrift.transport import TSSLSocket

將2處的代碼修改爲

transport = TSSLSocket.TSSLServerSocket(host="127.0.0.1", port=9090, certfile='cert.pem', keyfile='key.pem')

注意:其中certfile,keyfile記得替換爲你生成公私鑰的名字。

Client端

在這裏插入圖片描述
將1處的代碼修改爲

from thrift.transport import TSSLSocket

將2處的代碼修改爲

transport = TSSLSocket.TSSLSocket(host="127.0.0.1", port=9090, ca_certs='cert.pem')

注意:其中ca_certfile記得替換爲你生成公私鑰的名字。

Server完整代碼

import sys
sys.path.append('./gen-py')

from tutorial import Calculator
from tutorial.ttypes import InvalidOperation, Operation

from shared.ttypes import SharedStruct

from thrift.transport import TSSLSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
from thrift.server import TServer

class CalculatorHandler:
    def __init__(self):
        self.log = {}

    def ping(self):
        print('ping()')

    def add(self, n1, n2):
        print('add(%d,%d)' % (n1, n2))
        return n1 + n2

    def calculate(self, logid, work):
        print('calculate(%d, %r)' % (logid, work))

        if work.op == Operation.ADD:
            val = work.num1 + work.num2
        elif work.op == Operation.SUBTRACT:
            val = work.num1 - work.num2
        elif work.op == Operation.MULTIPLY:
            val = work.num1 * work.num2
        elif work.op == Operation.DIVIDE:
            if work.num2 == 0:
                raise InvalidOperation(work.op, 'Cannot divide by 0')
            val = work.num1 / work.num2
        else:
            raise InvalidOperation(work.op, 'Invalid operation')

        log = SharedStruct()
        log.key = logid
        log.value = '%d' % (val)
        self.log[logid] = log

        return val

    def getStruct(self, key):
        print('getStruct(%d)' % (key))
        return self.log[key]

    def zip(self):
        print('zip()')

    def echo(self, msg, cnt):
        print("%s,%d" % (msg, cnt))
        return cnt + 1

if __name__ == '__main__':
    handler = CalculatorHandler()
    processor = Calculator.Processor(handler)
    transport = TSSLSocket.TSSLServerSocket(host="127.0.0.1", port=9090, certfile='cert.pem', keyfile='key.pem')
    tfactory = TTransport.TBufferedTransportFactory()
    pfactory = TBinaryProtocol.TBinaryProtocolFactory()

    server = TServer.TSimpleServer(processor, transport, tfactory, pfactory)

    # You could do one of these for a multithreaded server
    # server = TServer.TThreadedServer(
    #     processor, transport, tfactory, pfactory)
    # server = TServer.TThreadPoolServer(
    #     processor, transport, tfactory, pfactory)

    print('Starting the server...')
    server.serve()
    print('done.')

Client完整代碼

import sys
import glob
sys.path.append('./gen-py')

from tutorial import Calculator
from tutorial.ttypes import InvalidOperation, Operation, Work

from thrift import Thrift
from thrift.transport import TSSLSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol

def main():
    # Make socket
    transport = TSSLSocket.TSSLSocket(host="127.0.0.1", port=9090, ca_certs='cert.pem')

    # Buffering is critical. Raw sockets are very slow
    transport = TTransport.TBufferedTransport(transport)

    # Wrap in a protocol
    protocol = TBinaryProtocol.TBinaryProtocol(transport)

    # Create a client to use the protocol encoder
    client = Calculator.Client(protocol)

    # Connect!
    transport.open()

    client.ping()
    print('ping()')

    sum_ = client.add(1, 1)
    print('1+1=%d' % sum_)

    work = Work()

    work.op = Operation.DIVIDE
    work.num1 = 1
    work.num2 = 0

    try:
        quotient = client.calculate(1, work)
        print('Whoa? You know how to divide by zero?')
        print('FYI the answer is %d' % quotient)
    except InvalidOperation as e:
        print('InvalidOperation: %r' % e)

    work.op = Operation.SUBTRACT
    work.num1 = 15
    work.num2 = 10

    diff = client.calculate(1, work)
    print('15-10=%d' % diff)

    log = client.getStruct(1)
    print('Check log: %s' % log.value)

    flag = client.echo("hello server!", 2020)
    print("hello server!,%d" % flag)

    # Close!
    transport.close()

if __name__ == '__main__':
    try:
        main()
    except Thrift.TException as tx:
        print('%s' % tx.message)

運行結果:
在這裏插入圖片描述

加密遠程通信版本

前期準備

  • 有效的證書
    在這裏插入圖片描述

修改代碼

已經有了使用證書通信的經驗,這次會容易得多。

首先PythonServer.py文件是沒有用的,因爲我們要連接的服務器在網絡上,網絡端是已經寫好的,我們只需要寫好客戶端去連接即可,也就是PythonClient.py。

其次需要把要連接的服務器IP改成真實的服務器IP,把證書改成你的證書即可。
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章