After building and executing the following sample I've obtained next output:
bind to: echosock
rv: 14 data: '[[[SomeData]]]' sz: 14 remAddrLen: 0
client sent: 14
Why remAddrLen
is zero? And corresponding remote address was not returned?
#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;
}
I've found the reason:
Corrected code:
#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;
}