-3

这个问题已经解决。根本原因是我传递了一个 C++ 临时对象作为 getpeername() 的 sockaddr*,该对象在 getpeername() 返回后被自动销毁。

因此,最终结果全为 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),为什么?

4

1 回答 1

3

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));
于 2013-02-15T07:46:34.377 回答