python 中采用 socketserver模块可以更方便地建立TCP,UDP服务器。
1.socketserver模块
2.步骤及代码
3.socketserver框架实现多线程服务器
1.socketserver模块
socketserver是python 的一个网络服务器框架,可以减少编写网络服务器程序的工作量。
socketserver模块只能用来写服务端
socketserver模块中使用的服务器类主要有 : TCPserver,UDPserver,ThreadingTCPserver,ThreadingUDPserver,ForkingTCPserver,ForkingUDPserver
有TCP字段的表示TCP协议服务器,有UDP字段的表示UDP协议服务器,有Threading字段的表示多线程,有Forking字段的表示多进程
socketserver模块中使用的处理器类主要有 : StreamRequestHandler(基于TCP协议) , DatagramRequestHandler(基于UDP协议)。处理器类中有一个十分重要的方法:handler() 。 处理器类用来做什么操作都是写在handler()里的
class myTcp(socketserver.StreamRequestHandler): #继承TCP的处理器类
def handle(self):
xxx #myTcp这个类要做的操作写在handler()里
工作模式:
socketserver 框架 分为两大类操作,一是 服务器类(就是上面的TCPserver,UDPserver等等),二是处理器类,处理器类用于处理数据接收或者传送,而服务器类用于处理客户端和服务端通信问题 。
只要继承其中一个处理器类(TCP 或 UDP),就可以自定义一个处理器类(自定义数据如何传送或接收)
2.步骤及代码
1.选择一个服务器类,并创建其对象(如对象叫 server)。
2.自定义处理器类(或叫请求类)的功能
3.调用对象(server)的serve_forever() 方法 来 启动服务器
基于socketserver 的TCP服务端
from socketserver import StreamRequestHandler as Tcp #选择 TCP的处理器类
import socketserver
host=''
port = 8888
addr = (host,port)
'''处理器类部分'''
class myTcp(Tcp): #第二步:自定义处理器类的功能(这也是一个请求--request)
def handle(self):
print('client\'s address:',self.client_address), #打印连接上的客户端的 ip地址
while True:
data = self.request.recv(1024) #从客户端接收信息
if not data:
break
print(data.decode('utf-8'))
self.request.sendall(data) #向客户端发送信息
if __name__ == '__main__':
'''服务器类部分'''
server = socketserver.TCPServer(addr,myTcp) #第一步:.选择一个服务器类,并创建其对象
server.serve_forever() #第三步:开启服务器
客户端代码:
from socket import *
host ='localhost' #我是本机操作,所以host写localhost,如果是连接外部的服务器,host就要等于服务器的ip地址
port =8888
bufsize = 1024
addr = (host,port)
client = socket(AF_INET,SOCK_STREAM)
client.connect(addr)
while True:
data = input()
if not data or data=='exit':
break
client.send(data.encode('utf-8'))
data = client.recv(bufsize)
if not data:
break
print (data.decode('utf-8'))
client.close()
from socketserver import DatagramRequestHandler as udp #选择 UDP的处理器类
import socketserver
host=''
port = 8888
addr = (host,port)
'''处理器类部分'''
class myUDP(udp): #第二步:自定义处理器类的功能(这也是一个请求--request)
def handle(self):
print('client\'s address:',self.client_address), #打印连接上的客户端的 ip地址
while True:
data = self.rfile.readline() #读取客户端发来的信息
if not data:
break
print(data.decode('utf-8'))
self.wfile.write(data) #向客户端发送信息
if __name__ == '__main__':
'''服务器类部分'''
server = socketserver.UDPServer(addr,myUDP) #第一步:.选择一个服务器类,并创建其对象
server.serve_forever() #第三步:开启服务器
UDP客户端:
from socket import *
host ='localhost'
port =8888
bufsize = 1024
addr = (host,port)
client = socket(AF_INET,SOCK_DGRAM)
while True:
data = input()
if not data or data=='exit':
break
client.sendto(data.encode('utf-8'),addr)
data,saddr= client.recvfrom(bufsize)
if not data:
break
print (data.decode('utf-8'))
client.close()
3.用socketserver框架实现多线程服务器
Threading.TCPServer(服务类) + StreamRequesetHandler(处理类或叫请求类) = TCP多线程服务器
多线程 TCP 服务端:
from socketserver import ThreadingTCPServer, StreamRequestHandler
class myTCP(StreamRequestHandler):
def handle(self):
while True:
data = self.request.recv(1024)
print ("receive from (%r):%r" % (self.client_address, data))
self.wfile.write(data)
if __name__ == "__main__":
host = "" #主机名,可以是ip,像localhost的主机名,或""
port =8888 #端口
addr = (host, port)
server = ThreadingTCPServer(addr, myTCP) #实例化一个 多线程TCP服务类
server.serve_forever() #开启
上面的代码运行后,就可以接受多个客户端发来的连接和信息。(客户端代码可以用 TCP客户端代码,文章有)
上面的代码还是有缺憾的,就是这个程序就只能运行一个多线程TCP。
下面我们试试,一个程序除了运行 一个多线程TCP外,还可以用其他多线程运行其他任务(如:计数任务)
[ 一个程序运行 多个不同功能的线程 ]
from socketserver import ThreadingTCPServer, StreamRequestHandler
import socketserver
import threading
import time
'''线程任务1'''
class myTCP(StreamRequestHandler): #TCP处理器类(或叫请求类) 在这里 作为一个 线程任务
def handle(self):
while True:
data = self.request.recv(1024)
print ("receive from (%r):%r" % (self.client_address, data))
self.wfile.write(data)
'''线程任务2'''
class Count(threading.Thread): #另一个线程任务,用于计数,暂且叫他计数线程
count = 0
def run(self):
while True:
self.count += 1
print('count = ',self.count)
time.sleep(1)
if __name__ == "__main__":
host = ""
port =8888
addr = (host, port)
'''实现一个多线程TCP服务器'''
server = ThreadingTCPServer(addr,myTCP) #实例化一个多线程TCP服务器类
server_thread = threading.Thread(target=server.serve_forever) #创建线程,线程用于TCP多线程
server_thread.start() #开启线程
'''实现循环计数'''
count_thread = Count() #创建计数线程
count_thread.start() #开启线程