与c相比,python中的套接字编程非常用户友好。程序员不必担心有关套接字的细节。在python中,用户有更多机会关注应用层而不是网络层。在本教程中,我们将开发一个能够处理HTTP流量的简单多线程代理服务器。它将主要基于基本的套接字编程思想。如果你对基础知识没有把握,我建议你在学习本教程之前先复习一下。
这是一个简单的代理服务器实现。在接下来的教程中,我们将逐步将其开发成一个非常有用的服务器。
首先,我们将通过三个简单的步骤来实现这个过程
1.创建传入套接字 我们在服务器类的_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('')[0] # get url url = first_line.split(' ')[1]
- 然后,我们找到请求的目标地址。地址是一个元组 (目的地ip地址、目的地端口号) .我们将从这个地址接收数据。
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),例如Geeksforgeks。org和volla!!您应该能够访问浏览器上的内容。
一旦服务器运行,我们就可以监控到客户端的请求。我们可以使用这些数据来监控正在进行的内容,或者我们可以根据内容开发统计数据。 我们甚至可以限制访问网站或将IP地址列入黑名单。我们将在接下来的教程中讨论更多此类功能。 接下来呢? 在接下来的教程中,我们将在代理服务器中添加以下功能。 –将域名列入黑名单 –内容监控 –伐木 –HTTP Web服务器+代理服务器
本教程的全部工作源代码都可用 在这里
如果您有任何问题/意见,请随时在评论部分发布。
关于作者:
平克什·巴贾提亚 来自印度海得拉巴。他本质上是个极客,有很多值得寻找的项目。他的项目工作可见一斑 在这里
如果你也想在这里展示你的博客,请参见 吉微博 在Geeksforgek上写客博。