victor_crimea
victor_crimea

Reputation: 65

udp server sending data to specific client until any recvfrom

I writing a library that should implement UDP-based protocol. I'm host A, remote is host B. I need to send message from host A, port 7011, to host B port 7011. Then Host B will answer to the host A, port 7011. Communication is async, so I need the udp which will listen for incoming messages, and also sometimes I need to send messages from the same port the server is binded to.

Here is how i'm creating and binding socket:

udp_server::udp_server(const std::string &localAddress, int localPort)
    : f_port(localPort), f_addr(localAddress) {
    char decimal_port[16];
    snprintf(decimal_port, sizeof(decimal_port), "%d", f_port);
    decimal_port[sizeof(decimal_port) / sizeof(decimal_port[0]) - 1] = '\0';
    struct addrinfo hints;
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_DGRAM;
    hints.ai_protocol = IPPROTO_UDP;
    int r(getaddrinfo(localAddress.c_str(), decimal_port, &hints, &f_addrinfo));
    if (r != 0 || f_addrinfo == NULL) {
        throw udp_client_server_runtime_error(
            ("invalid address or port for UDP socket: \"" + localAddress + ":" + decimal_port + "\"").c_str());
    }
    f_socket = socket(f_addrinfo->ai_family, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
    if (f_socket == -1) {
        freeaddrinfo(f_addrinfo);
        throw udp_client_server_runtime_error(
            ("could not create UDP socket for: \"" + localAddress + ":" + decimal_port + "\"").c_str());
    }
    r = bind(f_socket, f_addrinfo->ai_addr, f_addrinfo->ai_addrlen);
    if (r != 0) {
        freeaddrinfo(f_addrinfo);
        close(f_socket);
        throw udp_client_server_runtime_error(
            ("could not bind UDP socket with: \"" + localAddress + ":" + decimal_port + "\"").c_str());
    }
} 

And here I'm trying to send message:

ssize_t udp_server::sendto(std::string remoteHost, uint16_t port, const char *message, size_t messageLength) {
    struct sockaddr_in remote;
    remote.sin_family = AF_INET;
    remote.sin_port = htons(7011);
    remote.sin_addr.s_addr = ::inet_addr("10.8.0.6");

    socklen_t addrSize;
    addrSize = sizeof(remote);

    memset(remote.sin_zero, '\0', sizeof(remote.sin_zero));
    dout << "messageLength: " << messageLength << std::endl;
    return ::sendto(this->f_socket, message, messageLength, 0, (struct sockaddr *)&remote, addrSize);
}

But ::sendto always returns -1. And errno is set to 22, which means invalid argument. What is the possible solutions? Maybe overall structure is bad.

=== Solution === I've bind my server to locahost :( Should be 0.0.0.0 or INADDR_ANY.

Upvotes: 3

Views: 877

Answers (1)

dbush
dbush

Reputation: 223917

This error can occur if you bind to localhost and attempt to send to a non-local IP.

If you want to be able to send from any interface, you should bind to 0.0.0.0.

Also, in udp_server::sendto, you set remote.sin_port and remote.sin_addr to hardcoded values. You probably want to use the remoteHost and port parameters here.

Upvotes: 0

Related Questions