原始实现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# AddressHOST = ''PORT = 8000reply = 'Yes'# 创建套接字,绑定套接字到本地IP与端口s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind((HOST, PORT))# passively wait, 3: maximum number of connections in the queues.listen(3)# accept and establish connectionconn, addr = s.accept()# receive messagerequest = conn.recv(1024)print 'request is: ',requestprint 'Connected by', addr# send messageconn.sendall(reply)# close connectionconn.close()
将以上保存为文件org_ser.py
其次,客户端:我们主动使用connect()方法来搜索服务器端的IP地址和端口,以便客户可以找到服务器,并建立连接。
import socket# AddressHOST = '172.20.202.155'PORT = 8000request = 'can you hear me?'# configure sockets = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST, PORT))# send messages.sendall(request)# receive messagereply = s.recv(1024)print 'reply is: ',reply# close connections.close()
客户端保存为org_client.py
调试运行:
20170110-1.JPG
左上角是用浏览器对服务器进行访问的结果,服务器回传了“Yes”,对应服务器中的代码:reply = 'Yes'
。
中间图是服务器运行图,最下面是客户端运行图,可以看出客户端向服务器请求的内容为:request = 'can you hear me?'
,而客户端得到的反馈是“Yes”。
程序运行正常。
作者:rebirth_2017
链接:https://www.jianshu.com/p/a324616b89d1