2013-02-15 113 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));