前言
Python 提供了两个级别访问的网络服务。低级别的网络服务可用于编写简单的网络服务,但复杂一点的网络程序还是用现成的框架比较好。这样就可以专心事务逻辑,而不是套接字的各种细节。高级别的网络服务模块,即SocketServer模块简化了编写网络服务程序的任务量,同时SocketServer模块也是Python标准库中很多服务器框架的基础。
一、低级别的网络服务模块
低级别的网络服务模块,即socket模块,支持基本的socket服务,提供了标准的BSD Socket API,可以访问底层操作系统Socket接口的全部方法。
1、什么是socket
Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。
2、服务端
大致流程如下:
- 创建套接字:使用 socket 模块的 socket 函数来创建一个 socket 对象。socket 对象可以通过调用其他函数来设置一个 socket 服务。
- 绑定套接字:调用 bind(hostname, port) 函数来指定服务的 port(端口)
- 监听套接字:调用listen函数,指定最多允许多少个客户连接到服务器。它的值至少为1。收到连接请求后,这些请求需要排队,如果队列满,就拒绝请求。
- 等待接受连接:调用 socket 对象的 accept 方法。该方法等待客户端的连接,并返回 connection 对象,表示已连接到客户端。socket会时入“waiting”状态,也就是处于阻塞状态。客户请求连接时,方法建立连接并返回服务器。
实例如下:
#!/usr/bin/python3
# 文件名:server.py
# 导入 socket、sys 模块
import socket
import sys
# 创建 socket 对象 面向连接的是SOCK_STREAM,非连接的是SOCK_DGRAM
serversocket = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
# 获取本地主机名
host = socket.gethostname()
port = 9999
# 绑定端口号
serversocket.bind((host, port))
# 设置最大连接数,超过后排队
serversocket.listen(5)
while True:
# 建立客户端连接
clientsocket,addr = serversocket.accept()
print("连接地址: %s" % str(addr))
msg='欢迎访问菜鸟教程!'+ "\r\n"
clientsocket.send(msg.encode('utf-8'))
clientsocket.close()
3、客户端
大致流程如下:
- 使用 socket 模块的 socket 函数来创建一个 socket 对象。
- socket.connect(hostname, port ) 方法打开一个 TCP 连接到主机为 hostname 端口为 port 的服务商。
- 使用recv函数从服务端获取数据
- 关闭套接字
实例如下:
#!/usr/bin/python3
# 文件名:client.py
# 导入 socket、sys 模块
import socket
import sys
# 创建 socket 对象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 获取本地主机名
host = socket.gethostname()
# 设置端口号
port = 9999
# 连接服务,指定主机和端口
s.connect((host, port))
# 接收小于 1024 字节的数据
msg = s.recv(1024)
s.close()
print (msg.decode('utf-8'))
二、高级别的网络服务模块
高级别的网络服务模块 SocketServer, 它提供了服务器中心类,可以简化网络服务器的开发。
该模块定义了一些类来处理诸如TCP、UDP等网络请求,主要是通过两个主要的类来实现的:
- 服务器类:处理通信问题,监听套接字并接收连接等。
- 请求处理类:处理接收的数据,并将反馈发送到客户端。
这种实现将服务器的实现过程和请求处理的实现过程解耦,也意味着我们可以将不同的服务器实现和请求处理实现结合起来来处理一些定制的协议。
socketserver在python2中为SocketServer,在python3种取消了首字母大写,改名为socketserver。
1、服务端
实例如下:
import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
def handle(self):
try:
while True:
self.data=self.request.recv(1024)
print("{} send:".format(self.client_address),self.data)
if not self.data:
print("connection lost")
break
self.request.sendall(self.data.upper())
except Exception as e:
print(self.client_address,"连接断开")
finally:
self.request.close()
def setup(self):
print("before handle,连接建立:",self.client_address)
def finish(self):
print("finish run after handle")
if __name__=="__main__":
HOST,PORT = "localhost",9999
server=socketserver.TCPServer((HOST,PORT),MyTCPHandler)
server.serve_forever()
其中,socketserver模块中定义了5种服务器类:
- BaseServer(服务器的基类,定义了API)
- TCPServer(使用TCP/IP套接字)
- UDPServer(使用数据报套接字)
- UnixStreamServer(使用UNIX域套接字,只适用UNIX平台)
- UnixDatagramServer(使用UNIX域套接字,只适用UNIX平台)
2、客户端
实例如下:
import socket
client=socket.socket()
client.connect(('localhost',9999))
while True:
cmd=input("(quit退出)>>").strip()
if len(cmd)==0:
continue
if cmd=="quit":
break
client.send(cmd.encode())
cmd_res=client.recv(1024)
print(cmd_res.decode())
client.close()