python 實現一個簡單epoll socket

python 實現一個epoll

server

#!/usr/bin/env python
#-*- coding:utf-8 -*-

import socket
import select
import Queue

#建立socket對象
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#設置IP地址複用
serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
#ip地址和端口號
server_address = ("127.0.0.1", 8888)
#綁定IP地址
serversocket.bind(server_address)
#監聽,並設置最大鏈接數
serversocket.listen(10)
print  "服務器啓動成功,監聽IP:" , server_address
#服務端設置非阻塞
serversocket.setblocking(False)
#超時時間
timeout = 5

#建立epoll事件對象,後續要監控的事件添加到其中
epoll = select.epoll()
#註冊服務器監聽fd到等待讀事件集合
epoll.register(serversocket.fileno(), select.EPOLLIN)

#保存鏈接客戶端消息的字典,格式爲{}
message_queues = {}
#文件句柄到所對應對象的字典,格式爲{句柄:對象}
fd_to_socket = {serversocket.fileno():serversocket,}

while True:
  print "等待活動鏈接......"
  #輪詢註冊的事件集合,返回值爲[(文件句柄,對應的事件),(...),....]
  events = epoll.poll(timeout)
  if not events:
     print "epoll超時無活動鏈接,從新輪詢......"
     continue
  print "有" , len(events), "個新事件,開始處理......"

  for fd, event in events:
     socket = fd_to_socket[fd]
     #若是活動socket爲當前服務器socket,表示有新鏈接
     if socket == serversocket:
            connection, address = serversocket.accept()
            print "新鏈接:" , address
            #新鏈接socket設置爲非阻塞
            connection.setblocking(False)
            #註冊新鏈接fd到待讀事件集合
            epoll.register(connection.fileno(), select.EPOLLIN)
            #把新鏈接的文件句柄以及對象保存到字典
            fd_to_socket[connection.fileno()] = connection
            #以新鏈接的對象爲鍵值,值存儲在隊列中,保存每一個鏈接的信息
            message_queues[connection]  = Queue.Queue()
     #關閉事件
     elif event & select.EPOLLHUP:
        print 'client close'
        #在epoll中註銷客戶端的文件句柄
        epoll.unregister(fd)
        #關閉客戶端的文件句柄
        fd_to_socket[fd].close()
        #在字典中刪除與已關閉客戶端相關的信息
        del fd_to_socket[fd]
     #可讀事件
     elif event & select.EPOLLIN:
        #接收數據
        data = socket.recv(1024)
        if data:
           print "收到數據:" , data , "客戶端:" , socket.getpeername()
           #將數據放入對應客戶端的字典
           message_queues[socket].put(data)
           #修改讀取到消息的鏈接到等待寫事件集合(即對應客戶端收到消息後,再將其fd修改並加入寫事件集合)
           epoll.modify(fd, select.EPOLLOUT)
     #可寫事件
     elif event & select.EPOLLOUT:
        try:
           #從字典中獲取對應客戶端的信息
           msg = message_queues[socket].get_nowait()
        except Queue.Empty:
           print socket.getpeername() , " queue empty"
           #修改文件句柄爲讀事件
           epoll.modify(fd, select.EPOLLIN)
        else :
           print "發送數據:" , data , "客戶端:" , socket.getpeername()
           #發送數據
           socket.send(msg)

#在epoll中註銷服務端文件句柄
epoll.unregister(serversocket.fileno())
#關閉epoll
epoll.close()
#關閉服務器socket
serversocket.close()

client

#!/usr/bin/env python
#-*- coding:utf-8 -*-

import socket

#建立客戶端socket對象
clientsocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#服務端IP地址和端口號元組
server_address = ('127.0.0.1',8888)
#客戶端鏈接指定的IP地址和端口號
clientsocket.connect(server_address)

while True:
    #輸入數據
    data = raw_input('please input:')
    #客戶端發送數據
    clientsocket.sendall(data)
    #客戶端接收數據
    server_data = clientsocket.recv(1024)
    print '客戶端收到的數據:%s'  % server_data
    #關閉客戶端socket
相關文章
相關標籤/搜索