• 用select模拟一个socket server


    1, 必须在非阻塞模式下,才能实现IO的多路复用,否则一个卡住就都卡住了。(单线程下的多路复用)

    先检测自己,现在没有客户端连进来,所以会卡住。

    # 用select去模拟socket,实现单线程下的多路复用
    import select
    import socket
    import queue
    
    server = socket.socket()
    server.bind(('localhost', 9000))
    server.listen(1024)
    server.setblocking(False)  # 设置为不阻塞,accept/recv没有数据都不阻塞,只会报错。
    
    inputs = [server, ]  # 先检测自己,如果我有活动了,说明有客户端要连我了。
    outputs = []
    select.select(inputs, outputs, inputs)
    
    # 第一个参数:需要检测哪些链接就放进来。操作系统发现100个里面有1个在活动,就会返回这100个。
    
    # 第二个参数:
    
    # 第三个参数:让操作系统检测100个的哪个有问题,就把有问题的返回。还是把100个放到这里。
    
    server.accept() #没有链接也不阻塞,只是返回一个错误。
    

     运行结果:

    C:abccdxdddOldboypython-3.5.2-embed-amd64python.exe C:/abccdxddd/Oldboy/Py_Exercise/Day10/ex3_Client.py
    

    2. 客户端代码:

    import socket
    HOST = 'localhost'  # The remote host
    PORT = 9000  # The same port as used by the server
    
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((HOST, PORT))
    
    while True:
        msg = bytes(input(">>:"), encoding="utf8")
        s.sendall(msg)
        data = s.recv(1024)
        # print(data)
        print('Received', repr(data))  #repr:格式化输出
    
    s.close()
    

     服务器端:

    # 用select去模拟socket,实现单线程下的多路复用
    import select
    import socket
    import queue
    
    server = socket.socket()
    server.bind(('localhost', 9000))
    server.listen(1024)
    server.setblocking(False)  # 设置为不阻塞,accept/recv没有数据都不阻塞,只会报错。
    
    inputs = [server, ]  # 先检测自己,如果我有活动了,说明有客户端要连我了。
    outputs = []
    readable,writeable,exceptional=select.select(inputs, outputs, inputs)
    
    # 第一个参数:需要检测哪些链接就放进来。操作系统发现100个里面有1个在活动,就会返回这100个。
    
    # 第二个参数:
    
    # 第三个参数:让操作系统检测100个的哪个有问题,就把有问题的返回。还是把100个放到这里。
    
    print(readable,writeable,exceptional) #新来的链接会出现在readable里面,
    
    server.accept() #没有链接也不阻塞,只是返回一个错误。
    

     运行结果:fd=240 文件描述符

    C:abccdxdddOldboypython-3.5.2-embed-amd64python.exe C:/abccdxddd/Oldboy/Py_Exercise/Day10/ex3_Client.py
    [<socket.socket fd=240, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000)>] [] []
    
    Process finished with exit code 0
    

     3.

    # 用select去模拟socket,实现单线程下的多路复用
    import select
    import socket
    import queue
    
    server = socket.socket()
    server.bind(('localhost', 9000))
    server.listen(1024)
    server.setblocking(False)  # 设置为不阻塞,accept/recv没有数据都不阻塞,只会报错。
    
    inputs = [server, ]  # 先检测自己,如果我有活动了,说明有客户端要连我了。
    outputs = []
    readable,writeable,exceptional=select.select(inputs, outputs, inputs)
    
    # 第一个参数:需要检测哪些链接就放进来。操作系统发现100个里面有1个在活动,就会返回这100个。
    
    # 第二个参数:
    
    # 第三个参数:让操作系统检测100个的哪个有问题,就把有问题的返回。还是把100个放到这里。
    
    print(readable,writeable,exceptional) #新来的链接会出现在readable里面,
    
    for r in readable:
        conn,addr=server.accept() #没有链接也不阻塞,只是返回一个错误。
        print(conn,addr)
    

     客户端:

    import socket
    HOST = 'localhost'  # The remote host
    PORT = 9000  # The same port as used by the server
    
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((HOST, PORT))
    
    while True:
        msg = bytes(input(">>:"), encoding="utf8")
        s.sendall(msg)
        data = s.recv(1024)
        # print(data)
        print('Received', repr(data))  #repr:格式化输出
    
    s.close()
    

    运行结果:

    C:abccdxdddOldboypython-3.5.2-embed-amd64python.exe C:abccdxdddOldboyPy_ExerciseDay10select_socket_server2.py
    [<socket.socket fd=240, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000)>] [] []
    <socket.socket fd=336, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000), raddr=('127.0.0.1', 49587)> ('127.0.0.1', 49587)
    
    Process finished with exit code 0
    

     至此链接已经建立。

    4.最终版本

    服务器端:

    import select,socket
    server=socket.socket()
    server.bind(('localhost',9000))
    server.listen(1024) #最多可以监听1024个
    server.setblocking(False)
    inputs=[server,]
    outputs=[]
    while True:
        readable,writeable,exceptional=select.select(inputs,outputs,inputs) #select帮着去检测这100个链接
        print(readable,writeable,exceptional)
        for r in readable:
            if r is server:
                conn,addr=server.accept()
                print('来了个新链接',addr)
                inputs.append(conn)
            else:
                data=r.recv(1024)
                print('收到数据',data)
                r.send(data)
    

     客户端:

    import socket
    s=socket.socket()
    s.connect(('localhost',9000))
    while True:
        msg=bytes(input(">>:"),encoding='utf8')
        s.sendall(msg)
        data=s.recv(1024)
        print('Received',repr(data))
    s.close()
    

     运行结果:

    C:abccdxdddOldboypython-3.5.2-embed-amd64python.exe C:/abccdxddd/Oldboy/Py_Exercise/Day10/select_socket_server2.py
    [<socket.socket fd=232, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000)>] [] []
    来了个新链接 ('127.0.0.1', 61118)
    [<socket.socket fd=324, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000), raddr=('127.0.0.1', 61118)>] [] []
    收到数据 b'1'
    [<socket.socket fd=324, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000), raddr=('127.0.0.1', 61118)>] [] []
    收到数据 b'2'
    [<socket.socket fd=232, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000)>] [] []
    来了个新链接 ('127.0.0.1', 61119)
    [<socket.socket fd=328, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000), raddr=('127.0.0.1', 61119)>] [] []
    收到数据 b'3'
    [<socket.socket fd=328, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000), raddr=('127.0.0.1', 61119)>] [] []
    收到数据 b'4'
    [<socket.socket fd=324, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000), raddr=('127.0.0.1', 61118)>] [] []
    收到数据 b'7'
    [<socket.socket fd=328, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000), raddr=('127.0.0.1', 61119)>] [] []
    收到数据 b'8'
    

     一个server端,两个client端

  • 相关阅读:
    学用MVC4做网站六后台管理:6.1.3管理员修改密码
    学用MVC4做网站六后台管理:6.1.1管理员登录、6.1.2退出
    学用MVC4做网站六后台管理:6.1管理员(续)
    学用MVC4做网站六:后台管理(续)
    SiteCore Experience Analytics-路径分析地图
    sitecore教程路径分析器
    SiteCore Experience Analytics-体验分析
    sitecore系列教程之更改您的个人设置
    sitecore中的两种编辑工具介绍
    Sitecore CMS中如何管理默认字段值
  • 原文地址:https://www.cnblogs.com/momo8238/p/7384699.html
Copyright © 2020-2023  润新知