黑马程序员技术交流社区

标题: 【上海校区】python 之socketserver模块可以更方便地建立TCP,UDP服务器 [打印本页]

作者: 范志远    时间: 2018-5-21 19:10
标题: 【上海校区】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()里的
[python] view plain copy
1.        class myTcp(socketserver.StreamRequestHandler):    #继承TCP的处理器类  
2.            def handle(self):  
3.               xxx   #myTcp这个类要做的操作写在handler()里  


工作模式:
socketserver 框架 分为两大类操作,一是 服务器类(就是上面的TCPserver,UDPserver等等),二是处理器类,处理器类用于处理数据接收或者传送,而服务器类用于处理客户端和服务端通信问题 。
只要继承其中一个处理器类(TCP 或 UDP),就可以自定义一个处理器类(自定义数据如何传送或接收)

2.步骤及代码
1.选择一个服务器类,并创建其对象(如对象叫 server)。
2.自定义处理器类(或叫请求类)的功能
3.调用对象(server)的serve_forever() 方法 来 启动服务器

基于socketserver 的TCP服务端
[python] view plain copy
1.        from socketserver import StreamRequestHandler as Tcp     #选择 TCP的处理器类  
2.        import socketserver  
3.        host=''  
4.        port = 8888  
5.        addr = (host,port)  
6.          
7.        '''''处理器类部分'''  
8.        class myTcp(Tcp):                                   #第二步:自定义处理器类的功能(这也是一个请求--request)  
9.            def handle(self):  
10.                print('client\'s address:',self.client_address),    #打印连接上的客户端的 ip地址  
11.                while True:  
12.                    data = self.request.recv(1024)                      #从客户端接收信息  
13.                    if not data:  
14.                        break  
15.                    print(data.decode('utf-8'))  
16.                    self.request.sendall(data)                          #向客户端发送信息  
17.          
18.        if __name__ == '__main__':  
19.            '''''服务器类部分'''  
20.            server = socketserver.TCPServer(addr,myTcp)     #第一步:.选择一个服务器类,并创建其对象  
21.            server.serve_forever()                          #第三步:开启服务器  

客户端代码:
[python] view plain copy
1.        from socket import *  
2.          
3.        host ='localhost'<span style="white-space:pre;">    </span>#我是本机操作,所以host写localhost,如果是连接外部的服务器,host就要等于服务器的ip地址  
4.        port =8888  
5.        bufsize = 1024  
6.        addr = (host,port)  
7.        client = socket(AF_INET,SOCK_STREAM)  
8.        client.connect(addr)  
9.        while True:  
10.            data = input()  
11.            if not data or data=='exit':  
12.                break  
13.            client.send(data.encode('utf-8'))  
14.            data = client.recv(bufsize)  
15.            if not data:  
16.                break  
17.            print (data.decode('utf-8'))  
18.        client.close()  


基于 socketserver 的 UDP服务端代码:
[python] view plain copy
1.        from socketserver import DatagramRequestHandler as udp     #选择 UDP的处理器类  
2.        import socketserver  
3.        host=''  
4.        port = 8888  
5.        addr = (host,port)  
6.          
7.        '''''处理器类部分'''  
8.        class myUDP(udp):                                   #第二步:自定义处理器类的功能(这也是一个请求--request)  
9.            def handle(self):  
10.                print('client\'s address:',self.client_address),    #打印连接上的客户端的 ip地址  
11.                while True:  
12.                    data = self.rfile.readline()                #读取客户端发来的信息  
13.                    if not data:  
14.                        break  
15.                    print(data.decode('utf-8'))  
16.                    self.wfile.write(data)                       #向客户端发送信息  
17.          
18.        if __name__ == '__main__':  
19.            '''''服务器类部分'''  
20.            server = socketserver.UDPServer(addr,myUDP)     #第一步:.选择一个服务器类,并创建其对象  
21.            server.serve_forever()                          #第三步:开启服务器  


UDP客户端:
[python] view plain copy
1.        from socket import *  
2.          
3.        host ='localhost'  
4.        port =8888  
5.        bufsize = 1024  
6.        addr = (host,port)  
7.        client = socket(AF_INET,SOCK_DGRAM)  
8.          
9.        while True:  
10.            data = input()  
11.            if not data or data=='exit':  
12.                break  
13.            client.sendto(data.encode('utf-8'),addr)  
14.            data,saddr= client.recvfrom(bufsize)  
15.            if not data:  
16.                break  
17.            print (data.decode('utf-8'))  
18.        client.close()  




3.用socketserver框架实现多线程服务器


Threading.TCPServer(服务类)  +  StreamRequesetHandler(处理类或叫请求类)  =  TCP多线程服务器
多线程 TCP 服务端:
[python] view plain copy
1.        from socketserver import ThreadingTCPServer, StreamRequestHandler  
2.          
3.        class myTCP(StreamRequestHandler):   
4.            def handle(self):   
5.                while True:  
6.                    data = self.request.recv(1024)  
7.                    print ("receive from (%r):%r" % (self.client_address, data))  
8.                    self.wfile.write(data)  
9.            
10.        if __name__ == "__main__":   
11.            host = ""       #主机名,可以是ip,像localhost的主机名,或""   
12.            port =8888     #端口  
13.            addr = (host, port)   
14.                
15.            server = ThreadingTCPServer(addr, myTCP)   #实例化一个 多线程TCP服务类  
16.            server.serve_forever()                     #开启  
上面的代码运行后,就可以接受多个客户端发来的连接和信息。(客户端代码可以用 TCP客户端代码,文章有)




上面的代码还是有缺憾的,就是这个程序就只能运行一个多线程TCP。
下面我们试试,一个程序除了运行 一个多线程TCP外,还可以用其他多线程运行其他任务(如:计数任务)


[ 一个程序运行 多个不同功能的线程 ]
[python] view plain copy
1.        from socketserver import ThreadingTCPServer, StreamRequestHandler  
2.        import  socketserver  
3.        import threading  
4.        import time  
5.          
6.        '''''线程任务1'''  
7.        class myTCP(StreamRequestHandler):  #TCP处理器类(或叫请求类) 在这里 作为一个 线程任务  
8.            def handle(self):   
9.                while True:  
10.                    data = self.request.recv(1024)  
11.                    print ("receive from (%r):%r" % (self.client_address, data))  
12.                    self.wfile.write(data)  
13.          
14.        '''''线程任务2'''  
15.        class Count(threading.Thread):        #另一个线程任务,用于计数,暂且叫他计数线程  
16.            count = 0  
17.            def run(self):  
18.                while True:  
19.                    self.count += 1  
20.                    print('count = ',self.count)  
21.                    time.sleep(1)  
22.          
23.        if __name__ == "__main__":   
24.            host = ""  
25.            port =8888  
26.            addr = (host, port)   
27.          
28.            '''''实现一个多线程TCP服务器'''  
29.            server = ThreadingTCPServer(addr,myTCP)                  #实例化一个多线程TCP服务器类  
30.            server_thread = threading.Thread(target=server.serve_forever)   #创建线程,线程用于TCP多线程  
31.            server_thread.start()                                           #开启线程  
32.          
33.            '''''实现循环计数'''  
34.            count_thread = Count()                      #创建计数线程  
35.            count_thread.start()                        #开启线程  


作者: 似景    时间: 2018-5-23 09:20

作者: 吴琼老师    时间: 2018-7-5 16:49

作者: 不二晨    时间: 2018-7-10 14:54
奈斯




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2