Python精选生活不易 我用pythonPython 运维

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

2017-01-10  本文已影响519人  rebirth_2017

原始实现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”。

程序运行正常。

上一篇下一篇

猜你喜欢

热点阅读