2012-08-27 54 views
1

我正在編程一個TCP/IP套接字服務器。阻止接受

我的問題是,我接受呼叫阻塞和不接受任何新進來的連接時,我(例如)遠程登錄我的服務器和不發送任何數據。

當我發送任何或退出的telnet接受停止封鎖,我能處理的數據發送和接受開始接受新進來的連接。

main() { 
   socket = bind_listen(); 

   while(1) { 
       user_socket = accept(socket); 
       ssl = SSL_new(ctx); 
       SSL_set_fd(ssl, user_socket); 
       SSL_accept(ssl); 

       event.data.fd = user_socket; 
       event.events = EPOLLIN | EPOLLONESHOT; 

       epoll_proof = epoll_ctl(poll_fd, EPOLL_CTL_ADD, user_socket, &event); 
    } 
} 

有幾個線程epoll_wait()和處理數據。 有什麼想法?謝謝!

+1

顯示您的代碼,最好是可展示問題的最小可編譯示例。 –

+0

沒有提供足夠的細節,但它聽起來有點像你沒有使用非阻塞套接字。 (在POSIX,這意味着'fcntl'設置'O_NONBLOCK',在Windows中,這意味着一些涉及'ioctlsocket',並在這兩個這意味着處理上所有套接字調用'EAGAIN' /'EWOULDBLOCK'錯誤。) – asveikau

+0

我試圖添加O_NONBLOCK但這並沒有解決我的問題。 –

回答

1

首先,您應查詢監聽的文件描述符(與selectpollepoll/kqueue)和只有呼叫accept如果它是隨時閱讀。

其次,更具體地講,如果你要爲邊沿觸發epoll,您需要將您的插座中設置成非阻塞模式。然後,當有人告訴你,它已經準備好讀,你需要調用accept在一個循環,直到你用錯誤EAGAINEWOULDBLOCK返回-1 - 有可能是在等待一次對多個連接請求,邊沿觸發輪詢只提醒您開機狀態變化,所以你需要排空插座。

在一個非常,非常幼稚的方式,你可以廢除投票和與非阻塞套接字的工作,無論是在繁忙的循環,或與一種睡眠循環。但這是非常浪費的,並且與適當的解決方案(或者您的平臺提供的任何輪詢機制)相比,它不會爲您購買任何東西。

1

您可以使用多路複用器,例如select或poll系列。

這會告訴你,當你可以運行接受瓦特/出被封鎖。

我想選擇的是最簡單的解決方案,如果你不知道如何使用多路複用器:http://linux.die.net/man/2/select

這也將避免壞的情況如阻塞讀/寫。

+0

所以我需要首先調用select或epoll,並首先等待套接字上的事件?當有一個事件我不得不接受()? –

2

這是因爲你的程序是單線程的。在第一步中,它等待連接,然後在建立連接時等待輸入。
有幾個選項可以讓它等待幾個連接並接受它們:線程,選擇和fcntl。