Python中socket經ssl加密后server開多線程


        前幾天手擼Python socket代碼,擼完之后經過ssl加密,確保數據的安全,外加server端開啟多線程保證一個客戶端連接有一個線程來服務客戶端,走了不少的彎路,網上的信息啥的要么有ssl沒有服務端的多線程,要不只有多線程沒有加ssl加密,對於新手做這種需求還是有些困難的,這里,經過我!李帥帥的實踐得出各種版本的代碼以及最終終結版的代碼,話說婦聯4都他娘的葯終結了,還有幾天就上映了,說票挺貴的,這他娘的看個屁,大不了過半個月在啃,不知道黑寡婦最后咋樣了,嘖嘖,挺好的一個姑娘,那臉,那腰,那身材,那充滿對李帥帥愛意恆生的眼神,咳咳,不扯了不扯了,直接上代碼自己看

1.沒有ssl加密沒有線程前的server端

server.py
import ssl
import threading

class ListenServer(object):

    PORT = 8000  # 監聽的端口
    # IP = "127.0.0.1"
    IP = "127.0.0.1"

    def __init__(self):  # 初始化
        # 生成SSL上下文
        # 切記!!!!!加密一定要在跟客戶端連接前進行加密,否則沒有意義!!!!!!
        self.context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
        # 加載服務器所用證書和私鑰
        self.context.load_cert_chain('cert/server.crt', 'cert/server.key')
        # 開啟socket,
        try:
            #                           套接字:ipv4           TCP協議
            self.SOCK = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            # 綁定ip以及端口號
            self.SOCK.bind((self.IP, self.PORT))
            print("監聽iP: %s; 監聽Port: %s" % (self.IP, self.PORT))
            # 監聽數,也可以理解服務端一次性處理多少的客戶端的連接請求
            self.SOCK.listen(100)
        except Exception as e:
            print("socket errer!: %s" % e)
        else:
            print("success SOCKET!")

    def run_pro(self, act):
        '''
            程序的主要函數
            處理連接客戶端
        '''

        print("server running...\r\n")
        # act = active.Active()
        with self.context.wrap_socket(self.SOCK, server_side=True) as ssock:
            while True:
                client_socket, client_ip = ssock.accept()  # 獲取客戶端

                # p = Process(target=process, args=(
                # client_socket, client_ip))  # 開始新進程
                p = threading.Thread(target=act,args=(client_socket, client_ip))
                p.start()
                # p.join() #線程會等待


if __name__ == "__main__":
    s = ListenServer()
    s.run_pro()
View Code

沒有ssl加密沒有線程前的client端

import socket
import ssl

class client_ssl:
    def send_hello(self,):
        # 生成SSL上下文
        context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
        # 加載信任根證書
        context.load_verify_locations('cert/ca.crt')
        print("現在證書啥的都加載完成了")
        # 與服務端建立socket連接
        with socket.create_connection(('127.0.0.1', 8000)) as sock:
            print("准備連接啦")
            # 將socket打包成SSL socket
            # 一定要注意的是這里的server_hostname不是指服務端IP,而是指服務端證書中設置的CN,我這里正好設置成127.0.1而已
            with context.wrap_socket(sock, server_hostname='127.0.0.1') as ssock:

                # 向服務端發送信息
                print("向服務端發送信息")
                msg = "do i connect with server ?".encode("utf-8")
                ssock.send(msg)
                # 接收服務端返回的信息
                msg = ssock.recv(1024).decode("utf-8")
                print("receive msg from server :" , msg)
                ssock.close()

if __name__ == "__main__":
    client = client_ssl()
    client.send_hello()
View Code

2.沒有ssl加密,只在服務端開啟多線程的server

from socketserver import BaseRequestHandler,ThreadingTCPServer
import threading

class Hander(BaseRequestHandler):
    def handle(self):
        '''
        實現並發的效果就是重寫父類的handle方法(直接寫邏輯,連接准備listen()等都干好了)
        :return:
        '''
        address = self.client_address
        print(address, "客戶端連接了!!")
        while 1:
            # 接受客戶端的數據
            data = self.request.recv(1024)
            # 判斷連接與否
            if len(data) > 0:
                print("客戶端", address, data.decode("utf-8"))
                cur_thread = threading.current_thread()
                self.request.sendall('response'.encode("utf-8"))
            else:
                print("關閉連接")
                break

if __name__ == '__main__':
    HOST = '192.168.0.177'
    PORT = 8000
    ADDR = (HOST, PORT)
    server = ThreadingTCPServer(ADDR,Hander)
    print("listening")
    server.serve_forever()
View Code

3.沒有加線程的server端

#!C:\Python3.6.5\python.exe
# -*- coding: gbk -*-

import socket
import ssl
import threading


class WSGIServer(object):
    def __init__(self, port):
        """初始化對象"""
        # 生成SSL上下文
        self.context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)  # 指定ssl版本
        # 加載信任根證書
        self.context.load_cert_chain(certfile="cert/ca.crt", keyfile="cert/ca.key")
        # self.context.load_verify_locations('cert.pem')  # server端的證書
        # self.context.load_verify_locations('key.pem')  # server端的
        print("現在證書啥的都加載完成了")
        # 創建套接字
        print(self.context)
        self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 解決程序端口占用問題
        self.tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        # 綁定本地ip地址
        self.tcp_server_socket.bind(("127.0.0.1", port))
        # 將套接字變為監聽套接字,最大連接數量為100
        self.tcp_server_socket.listen(100)
        print("最大連接數是100昂")

    def run_forever(self):
        """設備連接"""
        print("等待設備的鏈接ing。。。")
        # 1.等待設備連接(通過ip地址和端口建立tcp連接)
        #   如果有設備連接,則會生成用於設備和服務器通訊的套接字:new_socket
        #   會獲取到設備的ip地址和端口
        print("等待生產新的套接字。。。")

        print("哎呀,等到了!!!")

        with self.context.wrap_socket(self.tcp_server_socket, server_side=True) as ssock:
            # print("這一步有錯")
            while 1:
                new_socket, client_addr = ssock.accept()
                print("設備{0}已連接".format(client_addr))


    def service_machine(self, new_socket, client_addr):
        """業務處理"""
        while 1:
            # 3.接收設備發送的數據,單次最大1024字節,按‘gbk’格式解碼
            receive_data = new_socket.recv(1024).decode("gbk")
            # 4.如果設備發送的數據不為空
            if receive_data:
                # 4.1 打印接收的數據,這里可以將設備發送的數據寫入到文件中
                # 獲取設備的ID信息
                print(receive_data)
                if receive_data[0:6] == "report":
                    response = "SET OK:" + receive_data
                else:
                    receive_data = receive_data[6:].split(",")[0]
                    # 拼接響應數據
                    response = "alarm=" + receive_data + ",Switch:clear"
                print(response)
                # 4.2 返回原數據作為應答,按‘utf-8’格式編碼
                new_socket.send(response.encode("utf-8"))
            # 5.當設備斷開連接時,會收到空的字節數據,判斷設備已斷開連接
            else:
                print('設備{0}斷開連接...'.format(client_addr))
                break

        # 關閉套接字
        new_socket.close()


def main(port):
    """創建一個WEB服務器"""
    wsgi_server = WSGIServer(port)
    print("服務器已開啟")
    wsgi_server.run_forever()


if __name__ == '__main__':
    port = 8000  # 指定端口
    main(port)
View Code

4.ssl+多線程的server端!!!!!!

#!C:\Python3.6.5\python.exe
# -*- coding: gbk -*-

import socket
import ssl
import threading


class WSGIServer(object):
    def __init__(self, port):
        """初始化對象"""
        # 生成SSL上下文
        self.context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)  # 指定ssl版本
        # 加載信任根證書
        self.context.load_cert_chain(certfile="cert/ca.crt", keyfile="cert/ca.key")
        # self.context.load_verify_locations('cert.pem')  # server端的證書
        # self.context.load_verify_locations('key.pem')  # server端的
        print("現在證書啥的都加載完成了")
        # 創建套接字
        print(self.context)
        self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 解決程序端口占用問題
        self.tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        # 綁定本地ip地址
        self.tcp_server_socket.bind(("127.0.0.1", port))
        # 將套接字變為監聽套接字,最大連接數量為100
        self.tcp_server_socket.listen(100)
        print("最大連接數是100昂")

    def run_forever(self):
        """設備連接"""
        print("等待設備的鏈接ing。。。")
        # 1.等待設備連接(通過ip地址和端口建立tcp連接)
        #   如果有設備連接,則會生成用於設備和服務器通訊的套接字:new_socket
        #   會獲取到設備的ip地址和端口
        print("等待生產新的套接字。。。")

        print("哎呀,等到了!!!")

        with self.context.wrap_socket(self.tcp_server_socket, server_side=True) as ssock:
            # print("這一步有錯")
            while 1:
                new_socket, client_addr = ssock.accept()
                print("設備{0}已連接".format(client_addr))

                #     # 2.創建線程處理設備的需求
                t1 = threading.Thread(target=self.service_machine, args=(new_socket, client_addr))
                t1.start()

    def service_machine(self, new_socket, client_addr):
        """業務處理"""
        while 1:
            # 3.接收設備發送的數據,單次最大1024字節,按‘gbk’格式解碼
            receive_data = new_socket.recv(1024).decode("gbk")
            # 4.如果設備發送的數據不為空
            if receive_data:
                # 4.1 打印接收的數據,這里可以將設備發送的數據寫入到文件中
                # 獲取設備的ID信息
                print(receive_data)
                if receive_data[0:6] == "report":
                    response = "SET OK:" + receive_data
                else:
                    receive_data = receive_data[6:].split(",")[0]
                    # 拼接響應數據
                    response = "alarm=" + receive_data + ",Switch:clear"
                print(response)
                # 4.2 返回原數據作為應答,按‘utf-8’格式編碼
                new_socket.send(response.encode("utf-8"))
            # 5.當設備斷開連接時,會收到空的字節數據,判斷設備已斷開連接
            else:
                print('設備{0}斷開連接...'.format(client_addr))
                break

        # 關閉套接字
        new_socket.close()


def main(port):
    """創建一個WEB服務器"""
    wsgi_server = WSGIServer(port)
    print("服務器已開啟")
    wsgi_server.run_forever()


if __name__ == '__main__':
    port = 8000  # 指定端口
    main(port)
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM