2016-02-10 73 views
0

我一直在嘗試用C++編寫一個簡單的聊天程序,並且遇到了套接字問題。以下代碼返回沒有明顯原因的WSA 10049錯誤

最後錯誤代碼爲(1):0
最後錯誤代碼爲(2):0
最後錯誤代碼爲(3):10049
最後錯誤代碼爲(4): 10022

在檢查MSDN頁面上的WSA錯誤之後,我發現10022是針對無效參數,而10049是試圖綁定到不可用的地址。我得出結論,10049錯誤導致10022錯誤,因爲我試圖在未綁定的套接字上偵聽。

之後,嘗試了幾個不同的地址來找到任何可用的地址,包括127.x.x.x,192.168.x.x,0.0.0.0,其中沒有一個可用。我跳進CMD,看到其他進程正在使用這些地址。有誰能指出我找到這個問題的根源的正確方向?

#include "stdafx.h" 
using namespace std; 

int main() 
{ 
    long SUCCESSFUL; 
    WSAData WinSockData; 
    WORD DLLVERSION; 

    DLLVERSION = MAKEWORD(2, 1); 

    SUCCESSFUL = WSAStartup(DLLVERSION, &WinSockData); 

    SOCKADDR_IN ADDRESS; 
    int AddressSize = sizeof(ADDRESS); 

    SOCKET sock_CONNECTION; 

    const CHAR addr[15] = "127.0.0.1"; 
    char buffer [sizeof(in_addr)]; 

    printf("Last error code was(1): %d\n", WSAGetLastError()); 

    sock_CONNECTION = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
    ADDRESS.sin_addr.s_addr = inet_pton(AF_INET, (const CHAR*)&addr, &buffer); 
    ADDRESS.sin_family = AF_INET; 
    ADDRESS.sin_port = htons(444); 

    printf("Last error code was(2): %d\n", WSAGetLastError()); 


    bind(sock_CONNECTION, (SOCKADDR *)&ADDRESS, AddressSize); 

    printf("Last error code was(3): %d\n", WSAGetLastError()); 

    listen(sock_CONNECTION, 5); 

    printf("Last error code was(4): %d\n", WSAGetLastError()); 
    //note to self: don't use %x when referring to WSAGetLastError, returns untrue value outside WSAerror regular field 
    pause(); 
    return 0; 
} 
+0

你試過1024以上的端口嗎? – Dmitri

+0

C不是C++不是C!不要添加不相關的標籤。 – Olaf

回答

1

首先,一般記:你需要檢查每次調用函數的返回值,並只打印出WSAGetLastError()的值,如果返回值表明函數返回一個錯誤。否則,只會通過查看先前調用留下的錯誤代碼值來迷惑自己,而與最近調用的調用沒有任何關係。也就是說,不是這樣做:

bind(sock_CONNECTION, (SOCKADDR *)&ADDRESS, AddressSize); 
printf("Last error code was(3): %d\n", WSAGetLastError()); 

...你應該這樣做:

if (bind(sock_CONNECTION, (SOCKADDR *)&ADDRESS, AddressSize) != 0) 
{ 
    printf("bind() failed, last error code was(3): %d\n", WSAGetLastError()); 
} 

...和所有你調用其他功能類似。 (請注意,不同的函數會返回不同的值以指示錯誤,因此您需要閱讀每個函數的文檔頁面以找出正確的方式來測試成功與失敗的返回值)

這就是說,我認爲具體問題如下:

ADDRESS.sin_addr.s_addr = inet_pton(AF_INET, (const CHAR*)&addr, &buffer); 

inet_pton()不返回地址;而如果地址對指定的地址族有效,則返回「1」;如果地址在指定的地址族中不可解析,則返回0;如果發生某些系統錯誤(在此情況下,將設置errno),則返回-1。因此,您正在寫入ADDRESS.sin_addr.s_addr的值爲-1,0或1;這些都不是bind()將要使用的有效地址。 (嗯,其實0可以使用;見下文,但電話仍然是錯誤的)

正確的方法調用inet_pton()會更喜歡這樣的:

int result = inet_pton(AF_INET, addr, &ADDRESS.sin_addr); 
if (result != 1) printf("inet_pton() failed, error code %d\n", WSAGetLastError()); 

...但我懷疑是你可能想要做的事情(接受任何網絡接口上的連接),你根本不需要調用inet_pton()。相反,您可以將ADDRESS.sin_addr.s_addr設置爲INADDR_ANY,然後bind()將綁定您的套接字,以便它將接受傳入的TCP連接,而不管它們來自哪個網絡接口。

// INADDR_ANY (aka 0) means "I don't care which network interface, accept connections on any of them" 
ADDRESS.sin_addr.s_addr = INADDR_ANY; 
+0

真棒回答,工作很棒! –