• Python 标准类库


    标准类库 - 因特网协议与支持之socketserver

    by:授客 QQ1033553122

    socketserver 模块,简化网络服务编写任务。

     

    创建服务的步骤

    1  通过子类化BaseRequestHandler 类,创建一个请求处理程序,并且重写handle()方法,该方法将处理接收到的请求

    2 传递服务器地址和请求处理程序类参数,实例化server类(如TCPServer)

    3 调用server对象的handle_request()、serve_forever()方法,处理单个、多个请求

     

    实例

    socketserver.TCPServer

    服务端(单线程服务器)

    #!/usr/bin/env python 3.4.0
    #-*- encoding:utf-8 -*-
     
    __author__ = 'shouke'
     
    import socketserver
     
    class MyTCPHandler(socketserver.BaseRequestHandler):
        """
        server使用的RequestHandler.
     
        每个客户端连接连接到服务器时都会被初始化一次,并且必须重写handle()方法以便同客户端交流。
        """
     
        def handle(self):
            while True:
                # self.request即为与客户端连接的TCP socker
                self.data = self.request.recv(1024).decode('utf-8').strip()
                print('receive data from client[host%s port%s]%s' % (self.client_address[0], self.client_address[1], self.data))
                if self.data == 'bye':
                    self.request.sendall(bytes('bye', encoding='utf-8'))
                    self.request.close()
                    break
                else:
                    self.request.sendall(self.data.upper().encode('utf-8'))
     
    if __name__ == '__main__':
        # 创建TCPSocket服务器,绑定到10.118.52.26地址上,端口8000
        server = socketserver.TCPServer(('10.118.52.26', 8000), MyTCPHandler)
     
        # 激活服务器,让服务器一直运行,直到按Ctrl+C
        server.serve_forever()
     
     
    客户端

    #!/usr/bin/env python 3.4.0

    #-*- encoding:utf-8 -*-

     

    __author__ = 'shouke'

     

    import socket

    import time

     

    if __name__ == '__main__':

        if_sock_connected = False

        try:

           

            # Create a socket (SOCK_STREAM means a TCP socket)

            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

     

            # Connect to server and send data

            sock.connect(('10.118.52.26', 8000))

     

            if_sock_connected = True # 标记socket是否已连接

            i = 0

     

            while i < 100:

                if i == 6:

                    sock.sendall(bytes('bye ', "utf-8"))

                else:

                    sock.sendall(bytes('hello world with tcp ', "utf-8"))

     

                # Receive data from the server

                received = str(sock.recv(1024), "utf-8")

                logger.info('receive data from server%s' % received)

                if received == 'bye':

                    break

     

                time.sleep(5)

     

                i += 1

        except Exception as e:

            logger.error('程序运行出错:%s' % e)

        finally:

            if if_sock_connected:

                sock.close()

     
    运行结果

     

     

    函数说明:

    BaseServer.serve_forever(poll_interval=0.5)

    处理shudown请求除外的请求。

     

    有关socket说明

    socket.socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None)

    使用给定的地址家族,socket 类型,协议号创建一个新的socket。

    family:默认为AF_INET,其它可选值有AF_INET6, AF_UNIX, AF_CAN or AF_RDS

    type:默认为SOCK_STREAM,其它可选值有 SOCK_DGRAM, SOCK_RAW ,或者其它SOCK_XXX常量

    protocol:通常为0或者忽略,当family为AF_CAN时,为CAN_RAW、CAN_BCM

     

     

    Socket 对象

    socket.close()

    标记socket为closed

     

    close()释放与连接关联的资源,但不一定立即关闭连接。如果要及时关闭连接,请在调用close()之前调用shutdown()。

     

    socket.connect(address)

    连接给定地址的远程socket

     

     

    socket.recv(bufsize[, flags])

    从socket接收数据。返回值即为接收的数据。

    buffsize:每次接收的最大数据量。.

    flags默认为0

     

    注意:为了同硬件和网络设备最佳匹配,buffsize应该为一个相对小的2次幂,比如4096

     

    socket.sendall(bytes[, flags])

    发送字节数据到socket。不同于send方法,该方法会持续发送bytes参数给定的数据,直到所有数据被发送、错误发生。如果发送成功,则返回None,否则抛出异常。没有方法判断到底成功发送了多少数据

     

    socket.send(bytes[, flags])

    发送字节数据到socket。返回发送字节数,如果只传输了部分数据,程序会尝试发送剩余数据。

     

    更多资料参考官方文档,socket模块

     

     

    服务端(多线程服务器)

    #!/usr/bin/env python 3.4.0

    #-*- encoding:utf-8 -*-

     

    __author__ = 'shouke'

     

    import socket

    import threading

    import socketserver

     

    class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):

     

        def handle(self):

            while True:

                # self.request即为与客户端连接的TCP socker

                self.data = self.request.recv(1024).decode('utf-8').strip()

                cur_thread = threading.current_thread()

                print('%s receive data from client[host%s port%s]%s' % (cur_thread.name, self.client_address[0], self.client_address[1], self.data))

     

                if self.data == 'bye':

                    self.request.sendall(bytes('bye', encoding='utf-8'))

                    self.request.close()

                    break

                else:

                    self.request.sendall((cur_thread.name + ' ' + self.data.upper()).encode('utf-8'))

     

     

    class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):

        pass

     

    def client(ip, port, message):

        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:

            sock.connect((ip, port))

            sock.sendall(bytes(message, 'ascii'))

            response = str(sock.recv(1024), 'ascii')

            print("Received: {}".format(response))

     

    if __name__ == "__main__":

        # 如果设置端口为0,则表示任意未被占用端口

        HOST, PORT = "localhost", 9000

     

        server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)

        ip, port = server.server_address

     

        # 开启该server的一个线程,该线程会为每个请求开启更多的线程

        server_thread = threading.Thread(target=server.serve_forever)

        # server退出时,终止线程

        #server_thread.setDaemon(True)

     

        server_thread.start()

        print("Server loop running in thread:", server_thread.name)

     

        # server.shutdown()

        # server.server_close()

     

     

    客户端

    #!/usr/bin/env python 3.4.0

    #-*- encoding:utf-8 -*-

     

    __author__ = 'shouke'

     

    import socket

    import time

     

    if __name__ == '__main__':

        if_sock_connected = False

        try:

            # 创建一个socket (SOCK_STREAM 表示为TCP socket)

            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

     

            # 连接到服务器

            sock.connect(('localhost', 9000))

     

            # 发送数据

            if_sock_connected = True

            i = 0

            while i < 100:

                if i == 6:

                    sock.sendall(bytes('bye ', "utf-8"))

                else:

                    sock.sendall(bytes('hello world with tcp ', "utf-8"))

                    print("sent data to server{}".format(bytes('hello world with tcp ', "utf-8")))

                # 从服务器接收数据

                received = str(sock.recv(1024), "utf-8")

                print('receive data from server%s' % received)

                if received == 'bye':

                    break

                time.sleep(1)

                i += 1

        except Exception as e:

            print('程序运行出错:%s' % e)

        finally:

            if if_sock_connected:

                sock.close()

     

     
     

    运行结果

     

     

     

     

    更多资料,烦参考官方文档,socketserver模块。

  • 相关阅读:
    LocalDateTime和Date使用@JsonFormat显示毫秒时间
    curl查看ip的几种方式
    thinkphp5.1生成缩略图很模糊
    ajax发送时禁用按钮
    thinkphp5 不使用form,用input+ajax异步上传图片
    GOLANG 闭包和普通函数的区别
    GOLANG 匿名函数笔记
    父级自适应自己高度且高度完全一致css
    子元素等高 css
    ios 用jquery为元素标签绑定点击事件时,ios上不执行点击事件
  • 原文地址:https://www.cnblogs.com/shouke/p/10498608.html
Copyright © 2020-2023  润新知