首页 > 技术文章 > python之SocketServer

iexperience 2018-07-03 16:52 原文

SocketServer是对socket的封装和简化。

部分转自:http://www.cnblogs.com/zhangkui/p/5655428.html

1.SocketServer内部使用 IO多路复用 以及 “多线程” 和 “多进程” ,从而实现并发处理多个客户端请求的Socket服务端。即:每个客户端请求连接到服务器时,Socket服务端都会在服务器是创建一个“线程”或者“进 程” 专门负责处理当前客户端的所有请求。

注:导入模块的时候 3.x版本是socketserver 2.x版本是SocketServer

1.ThreadingTCPServer

ThreadingTCPServer实现的Soket服务器内部会为每个client创建一个 “线程”,该线程用来和客户端进行交互。

  1. ThreadingTCPServer基础
    使用ThreadingTCPServer:

创建一个继承自 SocketServer.BaseRequestHandler 的类
类中必须定义一个名称为 handle 的方法
启动ThreadingTCPServer

服务端

import SocketServer
class MyServer(SocketServer.BaseRequestHandler):
def handle(self):
    conn = self.request
    conn.sendall('我是多线程')
    Flag = True
    while Flag:
        data = conn.recv(1024)
        if data == 'exit':
            Flag = False
        elif data == '0':
            conn.sendall('您输入的是0')
        else:
            conn.sendall('请重新输入.')
if __name__ == '__main__':
server = SocketServer.ThreadingTCPServer(('127.0.0.1',8009),MyServer)
server.serve_forever()

客户端

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import socket
ip_port = ('127.0.0.1',8009)
sk = socket.socket()
sk.connect(ip_port)
while True:
    data = sk.recv(1024)
    print 'receive:',data
    inp = input('please input:')
    sk.sendall(inp)
    if inp == 'exit':
    break
sk.close()

内部调用流程为:

    • 启动服务端程序
    • 执行 TCPServer.init 方法,创建服务端Socket对象并绑定 IP 和 端口
    • 执行 BaseServer.init 方法,将自定义的继承自SocketServer.BaseRequestHandler 的类 - MyRequestHandle赋值给 self.RequestHandlerClass
    • 执行 BaseServer.server_forever 方法,While 循环一直监听是否有客户端请求到达 ...
      当客户端连接到达服务器
    • 执行 ThreadingMixIn.process_request 方法,创建一个 “线程” 用来处理请求
    • 执行 ThreadingMixIn.process_request_thread 方法
    • 执行 BaseServer.finish_request 方法,执行 self.RequestHandlerClass() 即:执行 自定义 MyRequestHandler 的构造方法(自动调用基类BaseRequestHandler的构造方法,在该构造方法中又会调用 MyRequestHandler的handle方法)
ForkingTCPServer

ForkingTCPServer和ThreadingTCPServer的使用和执行流程基本一致,只不过在内部分别为请求者建立 “线程” 和 “进程”。

实例:

server side

import socketserver
 
class MyTCPHandler(socketserver.BaseRequestHandler): #socketserver必须要继承BaseRequestHandler,每一个客户端请求过来都要实例化class MyTCPHandler
 
    def handle(self):  #继承完必须重写handle,跟客户端交互都是在handle里面完成的。
        self.data = self.request.recv(1024).strip()
        print("{} wrote:".format(self.client_address[0])) #打印客户端地址
        print(self.data)
        self.request.sendall(self.data.upper())
 
if __name__ == "__main__":
    HOST, PORT = "localhost", 9999
 
    # Create the server, binding to localhost on port 9999
    server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler)
 
    # Activate the server; this will keep running until you
    # interrupt the program with Ctrl-C
    server.serve_forever()

client side

import socket
import sys
 
HOST, PORT = "localhost", 9999
data = " ".join(sys.argv[1:])
 
# Create a socket (SOCK_STREAM means a TCP socket)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 
try:
    # Connect to server and send data
    sock.connect((HOST, PORT))
    sock.sendall(bytes(data + "\n", "utf-8"))
 
    # Receive data from the server and shut down
    received = str(sock.recv(1024), "utf-8")
finally:
    sock.close()
 
print("Sent:     {}".format(data))
print("Received: {}".format(received))

1.必须自己创建一个请求处理类,并且这个类要继承BaseRequestHandler,并且还有重写父亲类里的handle()

2.必须实例化TCPServer ,并且传递server ip 和 你上面创建的请求处理类 给这个TCPServer

3.server.handle_request() #只处理一个请求

 server.serve_forever() #处理多个一个请求,永远执行

 

推荐阅读