• Selector 模型


    1.服务器端:

    import selectors
    import socket
    
    sel = selectors.DefaultSelector() #生成一个select对象
    
    def accept(sock, mask): #有新链接进来
        conn, addr = sock.accept()  # Should be ready
        print('accepted', conn, 'from', addr)
        conn.setblocking(False) #设置为非阻塞模式
        sel.register(conn, selectors.EVENT_READ, read) #把conn注册到sel中,此时回调函数是read,
        # 新链接如果有活动,就调read函数。因为此时客户端可能还没有开始发数据呢,所以把Conn也加入检测列表。
        #如果再有活动,就会调用read了。
    
    def read(conn, mask):
        data = conn.recv(1024)  # Should be ready
        if data:
            print('echoing', repr(data), 'to', conn)
            conn.send(data)  # Hope it won't block
    
        else:
            print('closing', conn)
            sel.unregister(conn) #取消注册
            conn.close() #关闭链接
    
    sock = socket.socket()
    sock.bind(('localhost', 9998))
    sock.listen(100)
    sock.setblocking(False)
    sel.register(sock, selectors.EVENT_READ, accept) #让sel监听sock,只要来一个新链接,就调accept函数
                                                     #先把sock对象自己加入到检测列表里面。
    
    while True:
        events = sel.select() #这里的select调用的可能是select或者是epoll,取决于系统支持的是哪个。
    #默认是阻塞的,有活动连接就返回活动的连接列表。第一次如果有活动,肯定是新链接进来了。新链接进来后,就会调用accept函数。
        for key, mask in events: #只要有活动的数据,就返回一个列表。
            callback = key.data #accept
            callback(key.fileobj, mask) #key.fileobj:文件句柄
    

     客户端:

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

     运行结果:

    多连接可以并发。

    多个用户接入:

    #_*_coding:utf-8_*_
    __author__ = 'Alex Li'
    
    
    import socket
    import sys
    
    messages = [ b'This is the message. ',
                 b'It will be sent ',
                 b'in parts.',
                 ]
    server_address = ('localhost', 9998)
    
    # Create a TCP/IP socket
    socks = [ socket.socket(socket.AF_INET, socket.SOCK_STREAM),
              socket.socket(socket.AF_INET, socket.SOCK_STREAM),
              socket.socket(socket.AF_INET, socket.SOCK_STREAM),
              socket.socket(socket.AF_INET, socket.SOCK_STREAM),
              socket.socket(socket.AF_INET, socket.SOCK_STREAM),
              ]
    
    # Connect the socket to the port where the server is listening
    print('connecting to %s port %s' % server_address)
    for s in socks:
        s.connect(server_address)
    
    for message in messages:
    
        # Send messages on both sockets
        for s in socks:
            print('%s: sending "%s"' % (s.getsockname(), message) )
            s.send(message)
    
        # Read responses on both sockets
        for s in socks:
            data = s.recv(1024)
            print( '%s: received "%s"' % (s.getsockname(), data) )
            if not data:
                print('closing socket', s.getsockname() )
    
  • 相关阅读:
    2020年. NET Core面试题
    java Context namespace element 'component-scan' and its parser class ComponentScanBeanDefinitionParser are only available on JDK 1.5 and higher 解决方法
    vue 淡入淡出组件
    java http的get、post、post json参数的方法
    vue 父子组件通讯案例
    Vue 生产环境解决跨域问题
    npm run ERR! code ELIFECYCLE
    Android Studio 生成apk 出现 :error_prone_annotations.jar (com.google.errorprone:error) 错误
    记忆解析者芜青【总集】
    LwIP应用开发笔记之十:LwIP带操作系统基本移植
  • 原文地址:https://www.cnblogs.com/momo8238/p/7389600.html
Copyright © 2020-2023  润新知