# HTTPS服务实现



## socket

```python
import ssl, socket, time
from typing import Tuple
if __name__ == "__main__":
    # SSL 协议版本看源码
    context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
    #context.load_cert_chain(certfile=‘key_pub.pem’, keyfile=‘key_priv.pem')   #可以分开定义公钥和私钥文件，也可以合并成一个文件
    context.load_cert_chain(certfile='cert.pem')
   
    bindsocket = socket.socket()
    bindsocket.bind(('127.0.0.1', 443))
    bindsocket.listen(5)
   
    newsocket, fromaddr = bindsocket.accept()
    connstream = context.wrap_socket(newsocket, server_side=True, do_handshake_on_connect=True)
   
    try:
        data = connstream.recv(1024)
        print(data)
        buf = 'Hi NN%f\n\n\n\n'%time.time()
        buf = buf.encode()
        connstream.send(buf)
    finally:
        connstream.shutdown(socket.SHUT_RDWR)
        connstream.close()
        bindsocket.close()
```

> 此例没有使用socketserver框架，目的在于测试ssl模块的用法。

## socketserver

```python
import socketserver, ssl, time
class MyHTTPSHandler_socket(socketserver.BaseRequestHandler):
    def handle(self):
        context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
        context.load_cert_chain(certfile="cert.pem")
        SSLSocket = context.wrap_socket(self.request, server_side=True)
        self.data = SSLSocket.recv(1024)
        print(self.data)
        buf = 'test HTTPS Server Handler%f'%time.time()
        buf = buf.encode()
        SSLSocket.send(buf)

if __name__ == "__main__":
    port = 443
    httpd = socketserver.TCPServer(('localhost', port), MyHTTPSHandler_socket)
    print('https serving at port', port)
    httpd.serve_forever()
```

> 说明：handle()函数负责所有与客户端的通信。客户端连接过来之后，ssl模块载入证书，并用SSLSocket对socket进行封装，屏蔽底层的加密通信细节。

## HTTPS文件服务器代码

{% hint style="info" %}
文件访问功能由SimpleHTTPRequestHandler实现，数据加密传输由ssl实现。
{% endhint %}

```python
import socketserver, ssl, time, http.server
class MyHTTPS_SimpleHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
    def setup(self):
        print('setup')
        context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
        context.load_cert_chain(certfile='cert.pem')
        SSLSocket = context.wrap_socket(self.request, server_side=True)
        self.rfile = SSLSocket.makefile('rb', self.rbufsize)
        self.wfile = SSLSocket.makefile('wb', self.wbufsize)
       
if __name__ == "__main__":
    port = 443
    httpd = socketserver.TCPServer(("localhost", port), MyHTTPS_SimpleHTTPRequestHandler)
    print('https serving at port', port)
    httpd.serve_forever()
```

> 最后，要指出的是setup()和handle()都是在客户端开始连接之后才被调用，从顺序上来说setup()先于handle()。
