2013-02-15 111 views
-2

問題已解決。根本原因是我傳遞了一個C++臨時對象作爲getPername()的sockaddr *,它在getPername()返回後自動銷燬。爲什麼getpeername()返回OK,但結果不符合預期?

因此,最終結果是滿了0。

對不起,我的疏忽。我已投票結束這篇文章。請投票結束。


#include <winsock2.h> 
#include <windows.h> 
#include <thread> 

using namespace std; 

void server() 
{ 
    sockaddr_in server_addr {}; 
    server_addr.sin_family  = AF_INET; 
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 
    server_addr.sin_port  = htons(1234); 

    SOCKET s_listening = socket(AF_INET, SOCK_STREAM, 0); 

    bind(s_listening, (sockaddr*)&server_addr, sizeof(server_addr)); 
    listen(s_listening, 5); 

    while (true) 
    { 
     auto s_new = accept(s_listening, 0, 0); 

     sockaddr_in client_addr {}; 
     int size = sizeof(client_addr); 
     auto ret = getpeername(s_new, (sockaddr*)&client_addr, &size); 
     // 
     // ret is 0, which means the call to getpeername is OK. 
     // But client_addr is full of 0s rather than "127.0.0.1:4". Why? 
     // 
    } 
} 

int main() 
{ 
    std::thread(server).detach(); 
    SOCKET s_client = socket(AF_INET, SOCK_STREAM, 0); 

    sockaddr_in client_addr {}; 
    client_addr.sin_family  = AF_INET; 
    client_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 
    client_addr.sin_port  = htons(4); 

    bind(s_client, (sockaddr*)&client_addr, sizeof(client_addr)); 

    sockaddr_in server_addr {}; 
    server_addr.sin_family  = AF_INET; 
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 
    server_addr.sin_port  = htons(1234); 

    connect(s_client, (sockaddr*)&server_addr, sizeof(server_addr)); 
    getchar(); 
} 

的代碼被編譯VC++ 2012然而,儘管調用函數getpeername返回OK,返回的數據是錯誤的(全0的),爲什麼呢?

+0

OT:你爲什麼不只是使用第二和第三個參數'接受()'得到同行? – alk 2013-02-15 07:43:16

+0

這是高度簡化的代碼,專注於關鍵問題。我的真正目的是在accept()之後很長時間才通過套接字獲取對端信息。 – xmllmx 2013-02-15 07:48:56

+1

在'sockaddr_in client_addr {};'中,空括號對的目的是什麼?這甚至編譯?沒有'=',所以不是初始化。 – unwind 2013-02-15 08:00:30

回答

2

getpeername()初始化一個sockaddr_<something>結構。如果<something>等於in它以二進制格式保存IP地址和端口。

它的確如此不是攜帶一個字符緩衝區,其中包含對等方的名稱/地址和端口的任何ASCII表示。

sockaddr_in中的值也按網絡字節順序保存。

要打印的地址和端口由OP的源代碼段的意見表示,你可以做如下:

#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 

... 

int sd = -1; /* init to invalid socket */ 

... /* get sd a proper value */ 

sockaddr_in sa = {0}; /* init to all zeros */ 
socklen_t sl = sizeof(sa); 
if (getpeername(sd, (sockaddr *) &sa, &sl)) 
    perror("getpeername() failed"); 
else 
    printf("peer is: %s:%hu\n", inetntoa(sa.sinaddr), ntohs(sa.sin_port));