美文网首页Python精选生活不易 我用pythonPython 运维
Python下web服务器的原始实现(socket实现)

Python下web服务器的原始实现(socket实现)

作者: rebirth_2017 | 来源:发表于2017-01-10 19:17 被阅读519次

    原始实现VS框架实现


    “掌握一个类似于框架的高级工具是有用的,但是基础的东西可以让你永远不被淘汰。不要被工具限制了自己的发展。

    ”在当今Python服务器框架 (framework, 比如Django, Twisted, web.py等等) 横行的时代,从底层的socket开始写服务器似乎是一个出力不讨好的笨方法。

    “框架的意义在于掩盖底层的细节,提供一套对于开发人员更加友好的API,并处理诸如MVC的布局问题。框架允许我们快速的构建一个成型而且成熟的Python服务器。然而,框架本身也是依赖于底层(比如socket)。对于底层socket的了解,不仅可以帮助我们更好的使用框架,更可以让我们明白框架是如何设计的。

    更进一步,

    ”如果拥有良好的底层socket编程知识和其他系统编程知识,你完全可以设计并开发一款自己的框架。如果你可以从底层socket开始,实现一个完整的Python服务器,支持用户层的协议,并处理好诸如MVC(Model-View-Control)、多线程(threading)等问题,并整理出一套清晰的函数或者类,作为接口(API)呈现给用户,你就相当于设计了一个框架。“

    我们已经看到:

    许多成功的网站都是利用动态语言(比如Python, Ruby或者PHP,比如twitter和facebook)快速开发,在网站成功之后,将代码转换成诸如C和JAVA这样一些效率比较高的语言,从而让服务器能更有效率的面对每天亿万次的请求。在这样一些时间,底层的重要性,就远远超过了框架。

    预备知识:TCP/IP和socket


    我们需要对网络传输,特别是TCP/IP协议和socket有一定的了解。socket是进程间通信的一种方法 (参考Linux进程间通信),它是基于网络传输协议的上层接口。socket有许多种类型,比如基于TCP协议或者UDP协议(两种网络传输协议)。其中又以TCP socket最为常用。

    socket接口是实际上是操作系统提供的系统调用。
    TCP socket与双向管道(duplex PIPE)有些类似,一个进程向socket的一端写入或读取文本流,而另一个进程可以从socket的另一端读取或写入,比较特别是,这两个建立socket通信的进程可以分别属于两台不同的计算机。

    所谓的TCP协议,就是规定了一些通信的守则,以便在网络环境下能够有效实现上述进程间通信过程。双向管道(duplex PIPE)存活于同一台电脑中,所以不必区分两个进程的所在计算机的地址,而socket必须包含有地址信息,以便实现网络通信。

    一个socket包含四个地址信息: 两台计算机的IP地址和两个进程所使用的端口(port)。IP地址用于定位计算机,而port用于定位进程 (一台计算机上可以有多个进程分别使用不同的端口)。

    TCP Socket

    TCP socket


    在互联网上,我们可以让某台计算机作为服务器。服务器开放自己的端口,被动等待其他计算机连接。当其他计算机作为客户,主动使用socket连接到服务器的时候,服务器就开始为客户提供服务。

    在Python中,我们使用标准库中的socket包来进行底层的socket编程。
    socket类型和函数详情请参见: Socket 类型 函数

    首先是服务器端:
    我们使用bind()方法来赋予socket以固定的地址和端口,并使用listen()方法来被动的监听该端口。当有客户尝试用connect()方法连接的时候,服务器使用accept()接受连接,从而建立一个连接的socket:

    import socket
    
    # Address
    HOST = ''
    PORT = 8000
    
    reply = 'Yes'
    
    # 创建套接字,绑定套接字到本地IP与端口
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind((HOST, PORT))
    # passively wait, 3: maximum number of connections in the queue
    s.listen(3)
    
    # accept and establish connectionconn, 
    addr = s.accept()
    
    # receive message
    request = conn.recv(1024)
    print 'request is: ',request
    print 'Connected by', addr
    
    # send message
    conn.sendall(reply)
    
    # close connection
    conn.close()
    

    将以上保存为文件org_ser.py

    其次,客户端:我们主动使用connect()方法来搜索服务器端的IP地址和端口,以便客户可以找到服务器,并建立连接。

    import socket
    
    # Address
    HOST = '172.20.202.155'
    PORT = 8000
    
    request = 'can you hear me?'
    
    # configure socket
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((HOST, PORT))
    
    # send message
    s.sendall(request)
    
    # receive message
    reply = s.recv(1024)
    print 'reply is: ',reply
    
    # close connection
    s.close()
    

    客户端保存为org_client.py

    调试运行:

    20170110-1.JPG

    左上角是用浏览器对服务器进行访问的结果,服务器回传了“Yes”,对应服务器中的代码:reply = 'Yes'

    中间图是服务器运行图,最下面是客户端运行图,可以看出客户端向服务器请求的内容为:request = 'can you hear me?',而客户端得到的反馈是“Yes”。

    程序运行正常。

    相关文章

      网友评论

        本文标题:Python下web服务器的原始实现(socket实现)

        本文链接:https://www.haomeiwen.com/subject/kdclbttx.html