1
votes

I have a question:

Is there any way and if there is how I can discover server address via broadcasts from client's point of view?

I read almost everything on the Internet and there is no information how I can discover server address without knowing its name (gethostbyname()). I need to create a client-server application with UDP where a Server sends broadcast and clients are supposed to discover it and send some text back to it.

As far as I know the client needs to create a socket then get host (server) address by gethostbyname() in order to have an address on which it could recvfrom() and then perform i.e. sendto().

Basically server starts only with port (command line parameter) on which creates its socket and bind() and client is also started with only port (command line parameter) and is supposed to discover server address via broadcasts. This is what I have so far:

SERVER:

   struct sockaddr_in addr;
    int socketfd,t=1;
    socketfd = make_socket(PF_INET,type);
    memset(&addr, 0, sizeof(struct sockaddr_in));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    if (setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR,&t, sizeof(t))) ERR("setsockopt");
    if(bind(socketfd,(struct sockaddr*) &addr,sizeof(addr)) < 0)  ERR("bind");

Then I would like to broadcast it to everywhere in the subnetwork from server but dunno why:(

CLIENT:

struct sockaddr_in addr;
    struct hostent *hostinfo;
    addr.sin_family = AF_INET;
    addr.sin_port = htons (port);
    hostinfo = gethostbyname(address);
    if(hostinfo == NULL)HERR("gethostbyname");
    addr.sin_addr = *(struct in_addr*) hostinfo->h_addr;

Here I would like to receive in some way what server broadcasted and send back some text.

EDIT: I would do that by:

int fd;
struct sockaddr_in addr;

fd = socket(PF_INET, SOCK_DGRAM, 0);

char buf[TEXT_SIZE];
socklen_t size=sizeof(addr);

recvfrom(fd, (char *)buf, sizeof(char[FILE_SIZE]), 0, &addr, &size);

But how do I set server to broadcast it so that client from the above code could receive it? I always sent it by:

sendto(fd, (char *)some_buffer, sizeof(some_buffer), 0, &addr, sizeof(addr));

But my server cannot discover clients addr because it has to first send the broadcast to all clients. So I cannot fill addr here because it is not set yet. Is there any way that server would first broadcast the message without knowing clients address? Server only creates a socket binds it and then needs to immediately broadcast some text. Thank you for replies.

2
Use recvfrom th receive frames and get the sender address.harper
"I read almost everything on the Internet ..." WHOW! ;-)alk
Did you do the suggested changes?rodolk

2 Answers

0
votes

There is a confusion in how you are tackling the problem.

gethostbyname will use the resolver to lookup the IP address based on the name provided. So you will need to provide the server name and have the mapping somewhere: it could be the corresponding entry in hosts file or a A (or AAAA) record in a DNS server.

But from your problem description, it seems you don't want to use gethostbyname to obtain the server IP address.

If the server is broadcasting UDP datagrams and your client knows the port to which it is braodcasting, the client can read the UDP datagram and obtain the source address.

BTW, the server code you show is not sending broadcast.

This looks as an exercise for a networking course.

0
votes

Here is the code. I assume server is sending broadcast and client hangs on recvfrom, I hope you know how to fix this, thank you.

SERVER:

#define _GNU_SOURCE 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <signal.h>
#include <netdb.h>
#include <fcntl.h>
#include <dirent.h>
#include <arpa/inet.h>
#define ERR(source) (perror(source),\
             fprintf(stderr,"%s:%d\n",__FILE__,__LINE__),\
             exit(EXIT_FAILURE))

int main(int argc, char **argv)
{
    if(argc != 2)
    {
        return EXIT_FAILURE;
    }

    int port = atoi(argv[1]);

    struct sockaddr_in addr;
    int server_socket, t = 1;
    socklen_t size = sizeof(addr);

    server_socket = socket(PF_INET, SOCK_DGRAM, 0);
    memset(&addr, 0, sizeof(struct sockaddr_in));

    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);

    if (setsockopt(server_socket, SOL_SOCKET, SO_BROADCAST ,&t, sizeof(t)))
        ERR("setsockopt");

    if(bind(server_socket,(struct sockaddr*) &addr,sizeof(addr)) < 0) 
        ERR("bind");

    char buf[12] = "FromServer";

    /* I assume here I broadcast message assuming I set all attributes properly */
    if(sendto(server_socket, buf, sizeof(char[12]), 0, (struct sockaddr *)&addr, sizeof(addr)) < 0)
    {
        printf("problem");
        return EXIT_FAILURE;
    }

    printf("Sent to client: %s \n", buf);

    sleep(2);

    if(TEMP_FAILURE_RETRY(close(server_socket))<0)
        ERR("close");

    printf("\n\n----------------- Server [%d] terminated. -----------------  \n", getpid());    
    return EXIT_SUCCESS;
}

CLIENT:

#define _GNU_SOURCE 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <signal.h>
#include <netdb.h>
#include <arpa/inet.h>
#define BACKLOG 10
#define ERR(source) (perror(source),\
             fprintf(stderr,"%s:%d\n",__FILE__,__LINE__),\
             exit(EXIT_FAILURE))
#define HERR(source) (fprintf(stderr,"%s(%d) at %s:%d\n",source,h_errno,__FILE__,__LINE__),\
             exit(EXIT_FAILURE))

int main(int argc, char **argv)
{
    int client_socket;

    if(argc != 2)
    {
        return EXIT_FAILURE;
    }

    /* client port */
    int port = atoi(argv[1]);

    client_socket = socket(PF_INET, SOCK_DGRAM, 0);

    char data[12];

    struct sockaddr_in addr;
    socklen_t size = sizeof(addr);

    /* Here I would like to receive server broadcast (i.e. some text) but it hangs for ever */
    if(recvfrom(client_socket, (char *)data, sizeof(char[12]), 0, &addr, &size) < 0)
    {
        return EXIT_FAILURE;
    }

    printf("Received from server: %s \n", data);

    if(TEMP_FAILURE_RETRY(close(client_socket))<0)
        ERR("close");

    printf("\n\n----------------- Client [%d] terminated. -----------------  \n", getpid());    
    return EXIT_SUCCESS;
}