吴裕雄--天生自然PythonDjangoWeb企业开发:框架基础和技术选型

简单的Web Server

import socket

eol1 = b'

'
eol2 = b'

'
body = '''Hello,world!<h1>tszrwyx</h1>'''
response_params = ['HTTP/1.0 200OK',
                   'Date:Sun,27 may 2018 01:01:01 GMT',
                   'Content-Type:text/plain;charset=utf-8',
                   'Content-Length:{}
.format(len(body.encode()))',
                   body]
response = '
'.join(response_params)

def handle_connection(conn, addr):
    print('oh,new conn',conn,addr)
    import time
    time.sleep(100)
    request = b''
    while((eol1 not in request)and(eol2 not in request)):
        request += conn.recv(1024)
    print(request)
    conn.send(response.encode()) #response转为bytes后传输
    conn.close()
    
def main():
    #socket.AF_INET用于服务器与服务器之间的网络通信
    #socket.SOCK_STREAM用于基于TCP的流式socket通信
    serversocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    #设置端口可复用,保证我们每次按Ctrl+C组合键之后,快速重启
    serversocket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    serversocket.bind(('127.0.0.1',8000))
    serversocket.listen(5)#设置backlog-socket连接最大排队数量
    print('http://127.0.0.1:8000')
    try:
        while(True):
            conn,address = serversocket.accept()
            handle_connection(conn,address)
    finally:
        serversocket.close()
        
if __name__=='__main__':
    main()

 多线程版的WEB SERVER

# coding:utf-8

import time
import errno
import socket
import threading

EOL1 = b'

'
EOL2 = b'

'
body = '''Hello, world! <h1> from the5fire</h1> - from {thread_name}'''

response_params = [
    'HTTP/1.0 200 OK',
    'Date: Sun, 27 may 2018 01:01:01 GMT',
    'Content-Type: text/plain; charset=utf-8',
    'Content-Length: {length}
',
    body,
]
response = '
'.join(response_params)

def handle_connection(conn, addr):
    print(conn, addr)
#     time.sleep(60)
    request = b""
    while EOL1 not in request and EOL2 not in request:
        request += conn.recv(1024)  
    print(request)
    current_thread = threading.currentThread()
    content_length = len(body.format(thread_name=current_thread.name).encode())
    print(current_thread.name)
    conn.send(response.format(thread_name=current_thread.name, length=content_length).encode())
    conn.close()

def main():
    # socket.AF_INET    用于服务器与服务器之间的网络通信
    # socket.SOCK_STREAM    基于TCP的流式socket通信
    serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 设置端口可复用,保证我们每次Ctrl C之后,快速再次重启
    serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    serversocket.bind(('127.0.0.1', 8000))
    # 可参考:https://stackoverflow.com/questions/2444459/python-sock-listen
    serversocket.listen(10)
    print('http://127.0.0.1:8000')
    serversocket.setblocking(1)  # 设置socket为非阻塞模式

    try:
        i = 0
        while True:
            try:
                conn, address = serversocket.accept()
            except socket.error as e:
                if e.args[0] != errno.EAGAIN:
                    raise
                continue
            i += 1
            print(i)
            t = threading.Thread(target=handle_connection, args=(conn, address), name='thread-%s' % i)
            t.start()
    finally:
        serversocket.close()

if __name__ == '__main__':
    main()

 

简单的WSGI application

WSGI协议分为两部分,其中一部分是Web Server或者Gateway,就像上面的代码一样,监听在某个端口上,接受外部的请求。另外一部分是Web Application,Web Server接受到请求之后会通过WSGI协议规定的方式把数据传递给Web Application,我们在Web Application中处理完之后,设置对应的状态和HEADER,之后返回body部分。Web Server拿到返回数据之后,再进行HTTP协议的封装,最终返回完整的HTTP Response数据。

# coding:utf-8

#这就是一个简单的application
def simple_app(environ, start_response):
    status = '200 OK'
    response_headers = [('Content-type', 'text/plain')]
    start_response(status, response_headers)
    return ['Hello world! -by the5fire 
']
# coding:utf-8

#运行application
import os
import sys

def run_with_cgi(application):
    environ = dict(os.environ.items())
    environ['wsgi.input'] = sys.stdin
    environ['wsgi.errors'] = sys.stderr
    environ['wsgi.version'] = (1, 0)
    environ['wsgi.multithread'] = False
    environ['wsgi.multiprocess'] = True
    environ['wsgi.run_once'] = True
    
    if environ.get('HTTPS', 'off') in ('on', '1'):
        environ['wsgi.url_scheme'] = 'https'
    else:
        environ['wsgi.url_scheme'] = 'http'
        
    headers_set = []
    headers_sent = []
    def write(data):
        #如果headers_set是空的话就抛出下面这个异常
        if not headers_set:
            raise AssertionError("write() before start_response()")
        elif not headers_sent:
            # Before the first output, send the stored headers
            status, response_headers = headers_sent[:] = headers_set
            sys.stdout.write('Status: %s
' % status)
            for header in response_headers:
                sys.stdout.write('%s: %s
' % header)
            sys.stdout.write('
')
        sys.stdout.write(data)
        sys.stdout.flush()
        
    def start_response(status, response_headers, exc_info=None):
        if exc_info:
            try:
                # Re-raise original exception if headers sent
                if headers_sent:
                    raise [exc_info[0],exc_info[1],exc_info[2]]
            finally:
                exc_info = None     # avoid dangling circular ref
        elif headers_set:
            raise AssertionError("Headers already set!")
        headers_set[:] = [status, response_headers]
        return write
    
    result = application(environ, start_response)
    try:
        for data in result:
            if data:    # don't send headers until body appears
                write(data)
        if not headers_sent:
            write('')   # send headers now if body was empty
    finally:
        if hasattr(result, 'close'):
            result.close()
            
if __name__ == '__main__':
    run_with_cgi(simple_app)
                

WSGI协议规定,application必须是一个callable对象,这意味这个对象可以是Python中的一个函数,也可以是一个实现了__call__方法的类的实例。比如这个:
class AppClass(object):
    status = '200 OK'
    response_headers = [('Content-type', 'text/plain')]

    def __call__(self, environ, start_response):
        print(environ, start_response)
        start_response(self.status, self.response_headers)
        return ['Hello AppClass.__call__
']
application = AppClass()

 正在更新中...

原文地址:https://www.cnblogs.com/tszr/p/12217549.html