1、 SocketServer最简单的使用方法: (1) 创建一个Handler类,继承自BaseRequestHandler,重写其handle(),在该方法中完成对请求的处理。 (2) 实例化一个Server类对象(根据不同的server类型选择不同的Server类)。并将IP、端口和Handler类传递给Server的构造函数。 (3) 调用server对象的server_forever()开启服务。 2、 Socket.server提供的类类型 (1) socketserver中类分为三种类型。一是Server类:BaseServer/TCPServer/UDPServer用来接收客户的请求。TCPServer处理TCP请求,UDPServer处理UDP请求。BaserServer是基类,不能直接使用。TCPServer继承自BaseServer,UDPServer继承自TCPServer。暂时不明白为什么UDPServer要继承自TCPServer,后面再说。 (2) 二是Handler类:BaseRequestHandler/DatagramRequestHandler/StreamRequestHandler用来处理每一个客户请求。一般用使用BaseRequestHandler就行,但StreamRequestHandler/DatagramRequestHandler提供了一些特别的功能,前者用来处理流式(TCP)请求,后者处理数据报(UDP)请求。Server每收到一个客户请求就会创建一个Handler类示例来处理该请求。默认情况下,TCPServer/UDPServer是单进程单线程的模型,依次处理每个客户请求,一个请求处理完毕才能接着处理下一个请求。 (3) 三是MixIn类:ForkingMixIn/ThreadingMixIn用来为Server提供多进程/多线程并发处理能力的。ForkingMixIn是多进程模型,ThreadingMixin是多线程模型。这里特别巧妙的是,你只要创建一个类,同时继承Server类和MixIn类就能自动获得并发处理请求的能力。该模块本身就直接提供了这种类。 3、 ThreadingTCPServer/TCPServer/ForkingTCPServer的区别: 这三个类其实就是对接收到request请求后的不同处理方法。 TCPServer是接收到请求后执行handle方法,如果前一个的handle没有结束,那么其他的请求将不会受理,新的客户端也无法加入。 而ThreadingTCPServer和ForkingTCPServer则允许前一连接的handle未结束也可受理新的请求和连接新的客户端,区别在于前者用建立新线程的方法运行handle,后者用新进程的方法运行handle。 #练习9:SocketServer 服务端: import SocketServer import threading class MyTCPHandler(SocketServer.BaseRequestHandler): def handle(self): while True: self.data = self.request.recv(1024).strip() cur_thread = threading.current_thread() print cur_thread if not self.data: print u"客户端:%s 退出!" % self.client_address[0] break print u"%s 内容:%s" % (self.client_address[0], self.data) self.request.sendall(self.data.upper()) if __name__ == "__main__": HOST, PORT = "47.98.155.208", 8001 server = SocketServer.ThreadingTCPServer((HOST, PORT), MyTCPHandler) server.serve_forever() 客户端: if __name__=="__main__": import socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) socket.connect(("'47.98.155.208', 8001")) import time time.sleep(2) socket.send("ls -al /home/WANGJING"+" ") print socket.recv(1024).deconde("gbk") socket.close() fd:file descriptor 文件描述符 fd_r_list, fd_w_list, fd_x_list = select.select(rlist, wlist, xlist, [timeout]) 参数: 可接受四个参数(前三个必须) rlist: wait until ready for reading wlist: wait until ready for writing(一般不使用) xlist: wait for an “exceptional condition” timeout: 超时时间 #练习10:select 单线程实现多线程效果 服务端: import socket import select s = socket.socket() s.bind(('127.0.0.1', 8888)) s.listen(5) r_list = [s, ] num = 0 while True: print u"开始进入监听状态..." rl, wl, error = select.select(r_list, [], [], 10) # 第一次执行循环体:客户端建立的连接的时候,rl和r_list分别是[s,]和[s,] # 执行连接之后,r_list变为了[s,conn] # 第二次执行循环体:rl和r_list分别是[conn,]和[s,conn],执行else逻辑 # #第n次执行循环体:rl和r_list分别是[conn,]和[s,conn],执行else逻辑 num += 1 print u'执行次数%s'% num print("rl's length is %s" % len(rl)) print("r_list length %s" % len(r_list)) print "--------------length:", len(rl) print [i for i in rl] for fd in rl: if fd == s: conn, addr = fd.accept() r_list.append(conn) msg = conn.recv(200) conn.sendall(('first----%s' % conn.fileno()).encode("gbk")) else: try: msg = fd.recv(200) fd.sendall('second'.encode()) except ConnectionAbortedError: r_list.remove(fd) s.close() 客户端: import socket flag = 1 s = socket.socket() s.connect(('127.0.0.1', 8888)) while flag: input_msg = raw_input('input>>>') if input_msg == '0': break s.sendall(input_msg.encode()) msg = s.recv(1024) print(msg.decode()) s.close()