socketserver

socketserver

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

特点:
socketserver自带多线程、多进程

socketserver中的两个类,可以解决两个问题:
server类:保证一直运行提供服务(连接循环)
request类:可以基于一个连接进行通信循环

  • 一 简单示例
  • 二 简单示例二
  • 三 模拟上传、下载功能
    • 1 客户端上传到服务端
    • 2 服务端下载到客户端

一 简单示例

客户端输入,服务端返回大写
ps:基于TCP的socketserver,实现了并发

server:

import socketserver


class MyFTP(socketserver.BaseRequestHandler):
    def handle(self):
        while True:
            data = self.request.recv(1024)
            self.request.send(data.upper())


if __name__ == '__main__':
    obj = socketserver.ThreadingTCPServer(('127.0.0.1', 8484), MyFTP)
    obj.serve_forever()

建立连接:
1.实例化连接类socketserver.ThreadingTCPServer(('172.0.0.1',8080),FTPserver)
执行通信循环:
2.永远接收连接obj.serve_forever()

通信:
1.MyServer必须继承socketserver.BaseRequestHandler
2.类中必须有方法handle方法
3.self.request.recv()self.request.send()self.request.sendall())完成发送和接收数据

client:

import socket

ip_port = ('127.0.0.1', 8484)
sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sk.connect(ip_port)

while True:
    msg = input('>>:').strip()
    if msg == '':
        continue
    sk.send(msg.encode('utf-8'))
    
    data = sk.recv(1024)
    print(data)

二 简单示例二

模拟客房服务

server:

import socketserver


class MyServer(socketserver.BaseRequestHandler):
    def handle(self):
        # print(self.request, self.client_address, self.server)
        conn = self.request
        conn.sendall('欢迎致电 小红足疗,学生请按1,白领请按2,...,如需帮助请按0.'.encode('utf8'))
        Flag = True
        while Flag:
            data = conn.recv(1024)
            data = data.decode('utf8')
            if data == 'exit':
                Flag = False
            elif data == '0':
                conn.sendall('您的通过可能会被录音...为您上钟的是...'.encode('utf8'))
            else:
                conn.sendall('请重新输入.'.encode('utf8'))


if __name__ == '__main__':
    server = socketserver.ThreadingTCPServer(('127.0.0.1', 8080), MyServer)
    server.serve_forever()

client:

import socket

ip_port = ('127.0.0.1', 8080)
sk = socket.socket()
sk.connect(ip_port)
sk.settimeout(5)

while True:
    data = sk.recv(1024)
    print('receive:', data.decode('utf8'))
    inp = input('please input:')
    sk.sendall(inp.encode('utf8'))
    if inp == 'exit':
        break

sk.close()

三 模拟上传、下载功能

基于TCP的socketserver,实现并发的上传、下砸功能

1 客户端上传到服务端

server:

import socketserver
import struct
import json
import subprocess
import os

class MYTCPServer(socketserver.BaseRequestHandler):
    max_packet_size = 8192

    coding='utf-8'

    file_path = os.path.dirname(os.path.dirname(__file__))

    server_dir='file_upload'

    def handle(self):
        while True:
            while True:
                try:
                    head_struct = self.request.recv(4)
                    if not head_struct:break

                    head_len = struct.unpack('i', head_struct)[0]
                    head_json = self.request.recv(head_len).decode(self.coding)
                    head_dic = json.loads(head_json)

                    print(head_dic)
                    #head_dic={'cmd':'put','filename':'a.txt','filesize':123123}
                    cmd=head_dic['cmd']
                    if hasattr(self,cmd):
                        func=getattr(self,cmd)
                        func(head_dic)
                except Exception:
                    break

    def put(self,args):
        file_path=os.path.normpath(os.path.join(
            self.file_path,
            self.server_dir,
            args['filename']
        ))

        filesize=args['filesize']
        recv_size=0
        print('----->',file_path)
        with open(file_path,'wb') as f:
            while recv_size < filesize:
                recv_data=self.request.recv(self.max_packet_size)
                f.write(recv_data)
                recv_size+=len(recv_data)
                print('recvsize:%s filesize:%s' %(recv_size,filesize))


if __name__ == '__main__':
    obj = socketserver.ThreadingTCPServer(('127.0.0.1',8586),MYTCPServer)
    obj.serve_forever()

client:

import socket
import struct
import json
import os



class MYTCPClient:
    address_family = socket.AF_INET

    socket_type = socket.SOCK_STREAM

    allow_reuse_address = False

    max_packet_size = 8192

    coding='utf-8'

    request_queue_size = 5

    def __init__(self, server_address, connect=True):
        self.server_address=server_address
        self.socket = socket.socket(self.address_family,
                                    self.socket_type)
        if connect:
            try:
                self.client_connect()
            except:
                self.client_close()
                raise

    def client_connect(self):
        self.socket.connect(self.server_address)

    def client_close(self):
        self.socket.close()

    def run(self):
        while True:
            inp=input(">>: ").strip()
            if not inp:continue
            l=inp.split()
            cmd=l[0]
            if hasattr(self,cmd):
                func=getattr(self,cmd)
                func(l)


    def put(self,args):
        cmd=args[0]
        filename=args[1]
        if not os.path.isfile(filename):
            print('file:%s is not exists' %filename)
            return
        else:
            filesize=os.path.getsize(filename)

        head_dic={'cmd':cmd,'filename':os.path.basename(filename),'filesize':filesize}
        print(head_dic)
        head_json=json.dumps(head_dic)
        head_json_bytes=bytes(head_json,encoding=self.coding)

        head_struct=struct.pack('i',len(head_json_bytes))
        self.socket.send(head_struct)
        self.socket.send(head_json_bytes)
        send_size=0
        with open(filename,'rb') as f:
            for line in f:
                self.socket.send(line)
                send_size+=len(line)
                print(send_size)
                print(line)
            else:
                print('upload successful')

client=MYTCPClient(('127.0.0.1',8586))
client.run()

2 服务端下载到客户端

未完...

posted @ 2017-05-04 17:29  六神酱  阅读(229)  评论(0编辑  收藏  举报