Python实现一个SocketServer服务

353 阅读3分钟

Socket

套接字(socket)是一个抽象层,应用程序可以通过它发送或接收数据,可对其进行像对文件一样的打开、读写和关闭等操作。套接字允许应用程序将I/O插入到网络中,并与网络中的其他应用程序进行通信。网络套接字是IP地址与端口的组合。

有一个大白话解释,我觉得还不错:mp.weixin.qq.com/s/IRl2skdag…

我们可能经常听到Socket编程,那么该怎么理解Socket?

按照百度百科解释:所谓套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。

在TCP/IP模型中,Sokcet就是处于传输层与应用层之间的一个抽象层,他是一组接口,用于应用进程与TCP/IP协议族之间通信。简单的来说,用户可以通过Socket组织符合TCP/IP的要求的数据,来实现对应的功能,而不必自己再写一套代码。

SocketServer

Python为了更方便的实现网络服务器,把对Socket的操作封装为了SocketServer,这样我们就能通过SocketServer来编写实现多用户、高并发的网络服务。网上有很多对SocketServer的讲解,我这里就不多说了。

今天我们用SocketServer实现一个服务器,上代码。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import time
import socketserver


class CustomTCPServerRequestHandler(socketserver.BaseRequestHandler):

    def handle(self):
        """处理每一个连接,执行终端连接逻辑"""
        print("handle exec ...", os.getpid())
        print("有客户端连接进来了...")
        print("10s倒计时...")
        time.sleep(10)

    def finish(self) -> None:
        print("finish 连接关闭。。。", self)


print("初始化... ")
server = socketserver.ForkingTCPServer(
    server_address=("0.0.0.0", 2022),
    RequestHandlerClass=CustomTCPServerRequestHandler
)
print("开启服务... ")
server.serve_forever()

上面的代码,我们实现了一个简单的Socket服务器。大家可以运行起来上面的代码,然后通过终端执行 ssh user@127.0.0.1 -p 2022 看看效果。

是的,其实这就是一个简单的网络服务器,基于 TCP 实现的服务,当我们在终端执行上面的命令是,其实就是与服务器的一次交互,也就是在两个进程之间完成了一次通信。当然你也可以用别的基于 TCP 的通信方式去连通他,都是可以的。

这个服务,有兴趣的可以看下源码中的执行步骤,其实算是一个回调,当 server.serve_forever() 执行之后,服务器等待连接,我们通过上述 ssh user@127.0.0.1 -p 2022 建立连接之后,socketserver 就通过内部 select poll epoll 进行轮询监听,读取到数据之后,回调执行 CustomTCPServerRequestHandler 相关的方法。

那么,写着么个网络服务器有什么作用呢?

我是这么想的,既然我们这个服务器可以接受来自终端的 ssh 请求,那我们是不是做一个这种的服务端,专门用于远程 ssh 访问,当和我们的服务器建立连接之后,我们再根据客户端传来的命令,去执行对应的操作。

这样的话,如果有命令想要远程登录一台真实机器,是不是可以通过我们这个服务器来实现。这就需要我们接收到客户端的命令之后,能在服务端通过代码执行远程登录操作,该怎么做呢?对,说到这里,我们前面说的 Paramiko 库就能用到了,我们可以利用这两个库完成客户端访问中间服务器,并给中间服务器发送一些指令,然后终端服务器去执行对应的指令。比如:我们登录到中间服务器之后,发送一个 ssh 命令,让中间服务器去远程登录一台机器,并执行一些命令。

下面,让我们一起用 SocketServer + Paramiko 实现这个中间服务器-伪终端吧。