📜  在Python创建代理 Web 服务器 |设置 1

📅  最后修改于: 2021-10-20 12:15:21             🧑  作者: Mango

与c相比, Python的套接字编程非常用户友好。程序员不必担心有关套接字的细节。在Python,用户有更多的机会关注应用层而不是网络层。在本教程中,我们将开发一个能够处理 HTTP 流量的简单多线程代理服务器。它主要基于基本的套接字编程思想。如果您不确定基础知识,那么我建议您在阅读本教程之前先复习一下。

这是代理服务器的简单实现。在接下来的教程中,我们将逐渐将其开发成一个非常有用的服务器。

首先,我们将通过 3 个简单的步骤完成该过程

1. 创建传入套接字
我们在 Server 类的 __init__ 方法中创建了一个 socket serverSocket。这将为传入的连接创建一个套接字。然后我们绑定套接字,然后等待客户端连接。

def __init__(self, config):
    # Shutdown on Ctrl+C
    signal.signal(signal.SIGINT, self.shutdown) 

    # Create a TCP socket
    self.serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # Re-use the socket
    self.serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

    # bind the socket to a public host, and a port   
    self.serverSocket.bind((config['HOST_NAME'], config['BIND_PORT']))
    
    self.serverSocket.listen(10) # become a server socket
    self.__clients = {}

2. 接受客户和流程
这是所有步骤中最简单但最重要的步骤。我们等待客户端的连接请求,一旦连接成功,我们就在一个单独的线程中分派请求,使我们可以用于下一个请求。这使我们能够同时处理多个请求,从而将服务器的性能提高了数倍。

while True:

    # Establish the connection
    (clientSocket, client_address) = self.serverSocket.accept() 
    
    d = threading.Thread(name=self._getClientName(client_address), 
    target = self.proxy_thread, args=(clientSocket, client_address))
    d.setDaemon(True)
    d.start()

3. 重定向流量
代理服务器的主要功能是充当源和目标之间的中间人。在这里,我们将从源获取数据,然后将其传递给客户端。

  • 首先,我们从接收到的请求数据中提取 URL。
# get the request from browser
request = conn.recv(config['MAX_REQUEST_LEN']) 

# parse the first line
first_line = request.split('\n')[0]

# get url
url = first_line.split(' ')[1]
  • 然后,我们找到请求的目标地址。地址是(destination_ip_address, destination_port_no)的元组。我们将从该地址接收数据。
http_pos = url.find("://") # find pos of ://
if (http_pos==-1):
    temp = url
else:
    temp = url[(http_pos+3):] # get the rest of url

port_pos = temp.find(":") # find the port pos (if any)

# find end of web server
webserver_pos = temp.find("/")
if webserver_pos == -1:
    webserver_pos = len(temp)

webserver = ""
port = -1
if (port_pos==-1 or webserver_pos < port_pos): 

    # default port 
    port = 80 
    webserver = temp[:webserver_pos] 

else: # specific port 
    port = int((temp[(port_pos+1):])[:webserver_pos-port_pos-1])
    webserver = temp[:port_pos] 
  • 现在,我们建立到目标服务器(或远程服务器)的新连接,然后将原始请求的副本发送到服务器。然后服务器将响应响应。所有响应消息都使用RFC 822的通用消息格式。
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.settimeout(config['CONNECTION_TIMEOUT'])
s.connect((webserver, port))
s.sendall(request)
  • 然后我们将服务器的响应重定向到客户端。 conn 是到客户端的原始连接。响应可能比我们在一次调用中收到的 MAX_REQUEST_LEN 大,因此,空响应标志着响应的结束。
while 1:
    # receive data from web server
    data = s.recv(config['MAX_REQUEST_LEN'])

    if (len(data) > 0):
        conn.send(data) # send to browser/client
    else:
        break

然后我们适当地关闭服务器连接并进行错误处理以确保服务器按预期工作。

如何测试服务器?
1. 在终端上运行服务器。保持运行并切换到您喜欢的浏览器。
2. 转到浏览器的代理设置并将代理服务器更改为“localhost”并将端口更改为“12345”。
3. 现在打开任何 HTTP 网站(不是 HTTPS),例如。 geeksforgeeks.org 和 volla !!您应该能够访问浏览器上的内容。

一旦服务器运行,我们就可以监控到达客户端的请求。我们可以使用这些数据来监控正在播放的内容,或者我们可以根据内容开发统计数据。
我们甚至可以限制对网站的访问或将 IP 地址列入黑名单。我们将在接下来的教程中处理更多此类功能。
接下来是什么?
在接下来的教程中,我们将在代理服务器中添加以下功能。
– 将域列入黑名单
– 内容监控
– 记录
– HTTP WebServer + ProxyServer

本教程的整个工作源代码可在此处获得

在Python创建代理 Web 服务器 | 2套

如果您有任何问题/意见,请随时在评论部分发布它们。

关于作者:

Pinkesh Badjatiya来自 IIIT Hyderabad。他是一个内心极客,拥有大量值得寻找的项目。他的项目工作可以在这里看到。

如果您还想在这里展示您的博客,请参阅 GBlog,了解 GeeksforGeeks 上的客座博客写作。