gpt4 book ai didi

sockets - 从 Unix 本地套接字接收错误的地址(抽象命名空间)

转载 作者:行者123 更新时间:2023-12-04 19:43:51 26 4
gpt4 key购买 nike

在构建并执行以下示例后,我获得了下一个输出:

bind to: echosock
rv: 14 data: '[[[SomeData]]]' sz: 14 remAddrLen: 0
client sent: 14



为什么 remAddrLen是零?并且没有返回对应的远程地址?
#include <cstdlib>
#include <cstdint>
#include <vector>
#include <iostream>
#include <thread>

namespace {
const char* SOCK_PATH = "echosock";
const char* TEST_DATA = "[[[SomeData]]]";
}

int main()
{
pid_t childPid = ::fork();
if (childPid == 0)
{
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // hack: wait until server is starting reading
const int d = ::socket(AF_UNIX, SOCK_DGRAM, 0);
if (d == -1)
{
perror("socket");
return EXIT_FAILURE;
}

struct sockaddr_un locAddr;
::memset(&locAddr, 0, sizeof(locAddr));
locAddr.sun_family = AF_UNIX;
::strncpy(locAddr.sun_path + 1, SOCK_PATH, sizeof(locAddr.sun_path) - 1);
const socklen_t locAddrLen = ::strlen(SOCK_PATH) + 1 + sizeof(locAddr.sun_family);
const int rv = ::sendto(d, TEST_DATA, ::strlen(TEST_DATA), 0, reinterpret_cast<sockaddr*>(&locAddr), locAddrLen);
std::cout << "client sent: " << rv << std::endl;
::close(d);
}
else if (childPid > 0)
{
const int d = ::socket(AF_UNIX, SOCK_DGRAM, 0);
if (d == -1)
{
perror("socket");
return EXIT_FAILURE;
}

std::cout << "bind to: " << SOCK_PATH << std::endl;
struct sockaddr_un locAddr;
::memset(&locAddr, 0, sizeof(locAddr));
locAddr.sun_family = AF_UNIX;
::strncpy(locAddr.sun_path + 1, SOCK_PATH, sizeof(locAddr.sun_path) - 1);
const socklen_t locAddrLen = ::strlen(SOCK_PATH) + 1 + sizeof(locAddr.sun_family);
if (::bind(d, reinterpret_cast<sockaddr*>(&locAddr), locAddrLen) == -1)
{
perror("bind");
::close(d);
return EXIT_FAILURE;
}
struct sockaddr_un remAddr;
socklen_t remAddrLen = sizeof(remAddr);
std::vector<char> buff(::strlen(TEST_DATA));
const int rv = ::recvfrom(d, buff.data(), buff.size(), 0, reinterpret_cast<sockaddr*>(&remAddr), &remAddrLen);
std::cout << "rv: " << rv << " data: '";
std::cout.write(buff.data(), buff.size());
std::cout << "' sz: " << buff.size() << " remAddrLen: " << remAddrLen << std::endl;

::close(d);
}
else
{
perror("fork");
return EXIT_FAILURE;
}

return EXIT_SUCCESS;
}

最佳答案

我找到了原因:

  • 客户端和服务器应该使用不同的地址(即使在同一个节点上)
  • 客户端也应该使用绑定(bind)。

  • 更正的代码:
    #include <sys/un.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <unistd.h>

    #include <cstdlib>
    #include <cstdint>
    #include <vector>
    #include <iostream>
    #include <thread>

    namespace {
    const char* SOCK_PATH1 = "echosock1";
    const char* SOCK_PATH2 = "echosock2";
    const char* TEST_DATA = "[[[SomeData]]]";
    }

    int main()
    {
    pid_t childPid = ::fork();
    if (childPid == 0)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(100)); // hack: wait until server is starting reading
    const int d = ::socket(AF_UNIX, SOCK_DGRAM, 0);
    if (d == -1)
    {
    perror("socket");
    return EXIT_FAILURE;
    }

    struct sockaddr_un locAddr;
    ::memset(&locAddr, 0, sizeof(locAddr));
    locAddr.sun_family = AF_UNIX;
    ::strncpy(locAddr.sun_path + 1, SOCK_PATH1, sizeof(locAddr.sun_path) - 1);
    const socklen_t locAddrLen = ::strlen(SOCK_PATH1) + 1 + sizeof(locAddr.sun_family);

    std::cout << "cl bind to: " << SOCK_PATH1 << std::endl;
    if (::bind(d, reinterpret_cast<sockaddr*>(&locAddr), locAddrLen) == -1)
    {
    perror("bind");
    ::close(d);
    return EXIT_FAILURE;
    }

    struct sockaddr_un remAddr;
    ::memset(&remAddr, 0, sizeof(remAddr));
    remAddr.sun_family = AF_UNIX;
    ::strncpy(remAddr.sun_path + 1, SOCK_PATH2, sizeof(remAddr.sun_path) - 1);
    const socklen_t remAddrLen = ::strlen(SOCK_PATH2) + 1 + sizeof(remAddr.sun_family);
    const int rv = ::sendto(d, TEST_DATA, ::strlen(TEST_DATA), 0, reinterpret_cast<sockaddr*>(&remAddr), remAddrLen);
    std::cout << "client sent: " << rv << " to " << SOCK_PATH2 << std::endl;
    ::close(d);
    }
    else if (childPid > 0)
    {
    const int d = ::socket(AF_UNIX, SOCK_DGRAM, 0);
    if (d == -1)
    {
    perror("socket");
    return EXIT_FAILURE;
    }

    std::cout << "bind to: " << SOCK_PATH2 << std::endl;
    struct sockaddr_un locAddr;
    ::memset(&locAddr, 0, sizeof(locAddr));
    locAddr.sun_family = AF_UNIX;
    ::strncpy(locAddr.sun_path + 1, SOCK_PATH2, sizeof(locAddr.sun_path) - 1);
    const socklen_t locAddrLen = ::strlen(SOCK_PATH2) + 1 + sizeof(locAddr.sun_family);
    if (::bind(d, reinterpret_cast<sockaddr*>(&locAddr), locAddrLen) == -1)
    {
    perror("bind");
    ::close(d);
    return EXIT_FAILURE;
    }

    struct sockaddr_un remAddr;
    socklen_t remAddrLen = sizeof(remAddr);
    std::vector<char> buff(::strlen(TEST_DATA));
    const int rv = ::recvfrom(d, buff.data(), buff.size(), 0, reinterpret_cast<sockaddr*>(&remAddr), &remAddrLen);
    std::cout << "rv: " << rv << " data: '";
    std::cout.write(buff.data(), buff.size());
    std::cout << "' sz: " << buff.size() << " remAddrLen: " << remAddrLen << std::endl;

    ::close(d);
    }
    else
    {
    perror("fork");
    return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
    }

    关于sockets - 从 Unix 本地套接字接收错误的地址(抽象命名空间),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42008851/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com