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

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

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端!!!!!!socket

#!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
相關文章
相關標籤/搜索