zoukankan      html  css  js  c++  java
  • 用select (多路复用)模拟一个 socket server

    需求:用select (多路复用)模拟一个 socket server。可以接收多并发。

    1. 一开始是检测自己,如果我有活动了,就说明有客户端要连我了。

    #用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个的哪个有问题,就把有问题的返回。
    
    server.accept()
    

     运行结果:卡住了,有客户端进来时才会不卡。

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

     2.服务器端

    #用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,] #先检测自己,如果我有活动了,说明有客户端要连我了。
    
    #inputs=[server,conn]
    
    outputs=[]
    
    while True:
    
        readable,writeable,exceptional=select.select(inputs,outputs,inputs)
    
        #第一个参数:操作系统发现100个里面有1个在活动,就会返回这100个。需要检测哪些链接就放进来。
    
        #第二个参数:
    
        #第三个参数:让操作系统检测100个的哪个有问题,就把有问题的返回。
    
        print(readable,writeable,exceptional)
    
        for r in readable:
    
            if r is server: #代表来了一个新链接
    
                conn,addr=server.accept()
    
                print('来了个新链接',addr)
    
                inputs.append(conn) #是因为这个新建立的连接还没有发数据过来,现在就接收的话,程序会报错。
    
                #所以要想实现这个客户端发数据来时server端能知道,就需要让select再监测这个Conn。
    
            else:
    
                data=conn.recv(1024)
    
                print('收到数据',data)
    
                conn.send(data)
    

     客户端:

    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()
    

     运行结果: 有2个链接的情况下,无法多次接收数据

    C:abccdxdddOldboypython-3.5.2-embed-amd64python.exe C:/abccdxddd/Oldboy/Py_Exercise/Day10/select_socket_server.py
    
    [<socket.socket fd=240, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000)>] [] []
    
    来了个新链接 ('127.0.0.1', 53605)
    
    [<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', 53605)>] [] []
    
    收到数据 b'1'
    
    [<socket.socket fd=240, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000)>] [] []
    
    来了个新链接 ('127.0.0.1', 60337)
    
    [<socket.socket fd=348, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000), raddr=('127.0.0.1', 60337)>] [] []
    
    收到数据 b'123'
    

     3. server端进行修改:

    #用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,] #先检测自己,如果我有活动了,说明有客户端要连我了。
    
    #inputs=[server,conn]
    
    outputs=[]
    
    while True:
    
        readable,writeable,exceptional=select.select(inputs,outputs,inputs)
    
        #第一个参数:操作系统发现100个里面有1个在活动,就会返回这100个。需要检测哪些链接就放进来。
    
        #第二个参数:
    
        #第三个参数:让操作系统检测100个的哪个有问题,就把有问题的返回。
    
        print(readable,writeable,exceptional)
    
        for r in readable:
    
            if r is server: #代表来了一个新链接
    
                conn,addr=server.accept()
    
                print('来了个新链接',addr)
    
                inputs.append(conn) #是因为这个新建立的连接还没有发数据过来,现在就接收的话,程序会报错。
    
                #所以要想实现这个客户端发数据来时server端能知道,就需要让select再监测这个Conn。
    
            else:
    
                data=r.recv(1024)
    
                print('收到数据',data)
    
                r.send(data) 
    
    
     至此运行正常
    
     
    
  • 相关阅读:
    刷题-力扣-223. 矩形面积
    刷题-力扣-135. 分发糖果
    刷题-力扣-134. 加油站
    刷题-力扣-343. 整数拆分
    刷题-力扣-162. 寻找峰值
    刷题-力扣-371. 两整数之和
    20191114-2 Beta事后诸葛亮会议
    Beta阶段贡献分配
    扛把子组20191114-4 Beta发布用户使用报告
    beta 2/2 阶段中间产物提交
  • 原文地址:https://www.cnblogs.com/momo8238/p/7384300.html
Copyright © 2011-2022 走看看