2014-11-05 18 views
1

我有一個用Python編寫的小型服務器/客戶端腳本。epoll和socket在分叉兒童接受問題

server.py創建一個新的套接字並生成兩個子節點。 在子進程中我註冊了EPOLLIN事件的socket des criptor,所以 我可以在子進程中對套接字進行接受。問題是,兩個孩子都在客戶端請求上通知了 ,但只有一個孩子接受了,另一個孩子則拋出了一個異常「[Errno 11]資源暫時不可用」。 如何防止所有兒童獲得通知,如果他們無法在套接字上進行接受?

--- --- server.py

import socket, time, os, select 

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
sock.bind(('127.0.0.1', 10000)) 
sock.listen(256) 
sock.setblocking(False) 


for _ in range(0,2): 

    pid = os.fork() 
    if pid == 0: #in child 
     poll = select.epoll() 
     poll.register(sock.fileno(), select.EPOLLIN) 
     while True: 
      events = poll.poll(2) # listening for events with 2 sec timeout 
      for fileno, event in events: 
       if event & select.EPOLLIN: # there is data on socket available 
        print("EPOLLIN in PID: " + str(os.getpid())) 
        try: 
         clientsock, addr = sock.accept() 
         clientsock.close() 
         print("accepted and closed in PID: " + str(os.getpid())) 
        except Exception as e: 
         print("PID: " + str(os.getpid()) + " " + str(e)) 


# we are in parent process, keep it live 
while True: 
    time.sleep(10) 

客戶端火災只有一個請求給服務器:

--- --- client.py

import socket, time, select, sys 

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.connect(('localhost',10000)) 
s.setblocking(False) 
s.close() 

執行「client.py」後,我得到服務器的以下輸出:

EPOLLIN in PID: 9424 
EPOLLIN in PID: 9425 
PID: 9424 [Errno 11] Resource temporarily unavailable 
accepted and closed in PID: 9425 

正如你所看到的,他們都得到一個EPOLLIN,但只有一個確實接受,其他的 一個拋出異常。

+0

是否可以忽略第二個客戶端中的錯誤? – 2014-11-05 11:04:24

回答

0

它的工作原理如下:您希望所有的孩子都能得到通知,看他們是否可以接受新客戶,並且他們都會收到通知。此刻epoll返回的時候都可以調用accept。但是,如果只有一個客戶端連接,則接受只能返回一次成功。如果多個客戶端連接,則其他接受也會成功。

所以,你實際上想要的只是當客戶端正在監聽隊列中時,只有儘可能多的孩子被喚醒。不幸的是,用系統定義的API沒有辦法做到這一點(這不是python的問題)。因此,通常的做法是忽略EAGAIN並等待下一個客戶端。

0

「資源暫時不可用」是EAGAIN,在這種情況下,這意味着您目前不能accept(),這是自然的,因爲其他進程已經做了accept()。 EAGAIN不是一個致命錯誤,在這種情況下可以忽略。或者,您可以在主進程中處理accept(),並使用隊列處理連接到工作進程的套接字。

對於實際使用(與實驗和學習相反),我熱烈地建議使用生產框架,如Twisted。