zoukankan      html  css  js  c++  java
  • 在python中编写socket服务端模块(二):使用poll或epoll

    在linux上编写socket服务端程序一般可以用select、poll、epoll三种方式,本文主要介绍使用poll和epoll编写socket服务端模块。

    使用poll方式的服务器端程序代码:

    import socket
    import select
    import Queue
    
    server_address=('10.0.2.15',21345)
    server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    server.setblocking(False)
    server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    server.bind(server_address)
    server.listen(5)
    
    message_queues={}
    #poll时间单位是毫秒
    timeout = 1000
    
    # Create a limit for the event
    READ_ONLY = ( select.POLLIN | select.POLLPRI | select.POLLHUP | select.POLLERR)
    READ_WRITE = (READ_ONLY|select.POLLOUT)
    
    # Set up the poller
    poller = select.poll()
    poller.register(server,READ_ONLY)
    #Map file descriptors to socket objects
    #server.fileno()是获得server这个socket的文件描述符,是int类型
    fd_to_socket = {server.fileno():server,}
    
    while True:
        
        events = poller.poll(timeout)
        #fd是描述符,flag是event状态,都是int类型
        for fd ,flag in  events:
            # Retrieve the actual socket from its file descriptor
            #s为当前的socket对象
            s = fd_to_socket[fd]
            
            if flag & (select.POLLIN | select.POLLPRI) :
                if s is server :
                    # A readable socket is ready to accept a connection
                    connection , client_address = s.accept()
                    print " Connection " , client_address
                    connection.setblocking(False)
                     
                    fd_to_socket[connection.fileno()] = connection
                    poller.register(connection,READ_ONLY)
                     
                    #Give the connection a queue to send data
                    message_queues[connection]  = Queue.Queue()
                else :
                    data = s.recv(1024)
                    if data:
                        # A readable client socket has data
                        print "  received %s from %s " % (data, s.getpeername())
                        message_queues[s].put(data)
                        poller.modify(s,READ_WRITE)
                    else :
                        # Close the connection
                        print "  closing" , s.getpeername()
                        # Stop listening for input on the connection
                        poller.unregister(s)
                        s.close()
                        del message_queues[s]
            elif flag & select.POLLHUP :
                #A client that "hang up" , to be closed.
                print " Closing ", s.getpeername() ,"(HUP)"
                poller.unregister(s)
                s.close()
            elif flag & select.POLLOUT :
                #Socket is ready to send data , if there is any to send
                try:
                    next_msg = message_queues[s].get_nowait()
                except Queue.Empty:
                    # No messages waiting so stop checking
                    print s.getpeername() , " queue empty"
                    poller.modify(s,READ_ONLY)
                else :
                    print " sending %s to %s" % (next_msg , s.getpeername())
                    s.send(next_msg)
            elif flag & select.POLLERR:
                #Any events with POLLERR cause the server to close the socket
                print "  exception on" , s.getpeername()
                poller.unregister(s)
                s.close()
                del message_queues[s]

    使用epoll方式的服务器端程序代码跟poll方式类似,具体代码如下:

    import socket
    import select
    import Queue
    
    server_address=('10.0.2.15',21345)
    server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    server.setblocking(False)
    server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    server.bind(server_address)
    server.listen(5)
    
    message_queues={}
    #poll时间单位是毫秒
    timeout = 1000
    
    # Create a limit for the event
    READ_ONLY = ( select.EPOLLIN | select.EPOLLPRI | select.EPOLLHUP | select.EPOLLERR)
    READ_WRITE = (READ_ONLY|select.EPOLLOUT)
    
    # Set up the poller
    epoller = select.epoll()
    epoller.register(server,READ_ONLY)
    #Map file descriptors to socket objects
    #server.fileno()是获得server这个socket的文件描述符,是int类型
    fd_to_socket = {server.fileno():server,}
    
    while True:
        print "Waiting for the next event"
        events = epoller.poll(timeout)
        print events
        #fd是描述符,flag是event状态
        for fd ,flag in  events:
            # Retrieve the actual socket from its file descriptor
            s = fd_to_socket[fd]
            
            if flag & (select.EPOLLIN | select.EPOLLPRI) :
                if s is server :
                    # A readable socket is ready to accept a connection
                    connection , client_address = s.accept()
                    print " Connection " , client_address
                    connection.setblocking(False)
                     
                    fd_to_socket[connection.fileno()] = connection
                    epoller.register(connection,READ_ONLY)
                     
                    #Give the connection a queue to send data
                    message_queues[connection]  = Queue.Queue()
                else :
                    data = s.recv(1024)
                    if data:
                        # A readable client socket has data
                        print "  received %s from %s " % (data, s.getpeername())
                        message_queues[s].put(data)
                        epoller.modify(s,READ_WRITE)
                    else :
                        # Close the connection
                        print "  closing" , s.getpeername()
                        # Stop listening for input on the connection
                        epoller.unregister(s)
                        s.close()
                        del message_queues[s]
            elif flag & select.EPOLLHUP :
                #A client that "hang up" , to be closed.
                print " Closing ", s.getpeername() ,"(HUP)"
                epoller.unregister(s)
                s.close()
            elif flag & select.POLLOUT :
                #Socket is ready to send data , if there is any to send
                try:
                    next_msg = message_queues[s].get_nowait()
                except Queue.Empty:
                    # No messages waiting so stop checking
                    print s.getpeername() , " queue empty"
                    epoller.modify(s,READ_ONLY)
                else :
                    print " sending %s to %s" % (next_msg , s.getpeername())
                    s.send(next_msg)
            elif flag & select.EPOLLERR:
                #Any events with POLLERR cause the server to close the socket
                print "  exception on" , s.getpeername()
                epoller.unregister(s)
                s.close()
                del message_queues[s]
    


    客户端程序代码与上一篇博文中的相同。

  • 相关阅读:
    JAVA联调接口跨域解决办法
    Quartz集成springMVC 的方案二(持久化任务、集群和分布式)
    Quartz集成springMVC 的方案一
    Java 常调用的Webservice接口的方法
    集成Dubbo服务(Spring)
    Dubbo与Zookeeper、SpringMVC整合和使用(负载均衡、容错)
    事务的隔离级别 数据库
    Spring 之注解事务 @Transactional
    Request To JavaBean(请求对象转换为JavaBean对象)
    springmvc+mongodb+maven 项目搭建配置
  • 原文地址:https://www.cnblogs.com/james1207/p/3320361.html
Copyright © 2011-2022 走看看