2008-11-07 27 views
7

我使用winsock和C++來設置服務器應用程序。我遇到的問題是撥打listen會導致第一次機會例外。我想通常這些可以被忽略(?),但我發現其他人有同樣的問題,我在哪裏它導致應用程序每隔一段時間掛起。任何幫助將不勝感激。套接字例外:「端點映射程序中沒有更多端點可用」

的第一次機會異常是:0x000006D9:在MyApp的 .EXE在爲0x * 12345678 *

第一次機會異常有可從終結點映射器沒有更多的終結點。

我發現了一些證據表明這可能是由套接字造成的而我正在使用的代碼如下。在從底部開始的第五行調用listen時發生異常。

m_accept_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 

    if (m_accept_fd == INVALID_SOCKET) 
    { 
    return false; 
    } 

    int optval = 1; 

    if (setsockopt (m_accept_fd, SOL_SOCKET, SO_REUSEADDR, 
        (char*)&optval, sizeof(optval))) 
    { 
    closesocket(m_accept_fd); 
    m_accept_fd = INVALID_SOCKET; 
    return false; 
    } 

    struct sockaddr_in local_addr; 
    local_addr.sin_family = AF_INET; 
    local_addr.sin_addr.s_addr = INADDR_ANY; 
    local_addr.sin_port = htons(m_port); 

    if (bind(m_accept_fd, (struct sockaddr *)&local_addr, 
      sizeof(struct sockaddr_in)) == SOCKET_ERROR) 
    { 
    closesocket(m_accept_fd); 
    return false; 
    } 

    if (listen (m_accept_fd, 5) == SOCKET_ERROR) 
    { 
    closesocket(m_accept_fd); 
    return false; 
    } 
+0

這聽是隻在啓動時執行嗎?端口是否與動態綁定?您同時收聽多少個端口? – 2008-11-07 16:59:49

回答

6

在一個非常繁忙的服務器上,您可能會耗盡套接字。您可能需要調整一些TCPIP參數。調整這兩個註冊表:

HKLM\System\CurrentControlSet\Services\Tcpip\Parameters 
    MaxUserPort REG_DWORD 65534 (decimal) 
    TcpTimedWaitDelay REG_DWORD 60 (decimal) 

默認情況下,如果釋放的網絡端口(插座),當它可以重複使用之間的延遲幾分鐘。另外,根據操作系統版本的不同,windows將使用的範圍只有幾千個。在服務器上,在命令提示符下運行以下命令:

的netstat -an

,並在結果看(管到一個文件是最容易:netstat的-an> netstat.txt)。如果您在Timed Wait Delay狀態下看到1025-> 5000的大量端口,那麼這是您的問題,可以通過使用上面的註冊表項將最大用戶端口從5000調整到65534來解決。您還可以通過使用上面的註冊表項更快地回收端口來調整延遲。

如果這不是問題,那麼問題可能是您在Listen()方法中設置的掛起連接的數量。

0

這不會直接回答你的問題,但因爲你是用C++,我會建議使用像Boost::Asio東西來處理你的套接字代碼。這可以讓你對winsock API有一個很好的抽象,並且可以讓你更容易地診斷錯誤條件。

1

呃,也許是因爲你限制了最大數量的傳入連接?

listen (m_accept_fd, 5) 
// Limit here  ^^^ 

如果您允許更大的積壓,您應該能夠處理您的問題。使用這樣的SOMAXCONN的,而不是5

另外,如果你的問題是隻在服務器啓動時,您可能要關閉LINGER(SO_LINGER),以防止賴在那裏阻止套接字連接...

+0

更換爲SOMAXCONN並沒有幫助,但這肯定是我會帶給我的一個提示。 LINGER也沒有幫助:-( – 2008-11-07 19:15:02

2

你真的看到了一個問題,例如,程序是否因未處理的異常而結束?

即使沒有問題,調試器也可能會打印該消息,例如,請參閱here

3

原始問題與winsock無關。以上所有答案都是錯誤的。忽略第一次機會異常,它不是應用程序的問題,只是一些內部錯誤處理。