2

I've bumped into a problem with my broadcasting server. basically, I want it to send broadcasts continuously from the moment I launch it. for some reason it will not start until it receives a connection from somewhere. I must have messed up something but I can't realise what.

here is my code:

WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);
    SOCKET sock;
    sock = socket(AF_INET, SOCK_DGRAM, 0);
    char broadcast = 'a';

    if(setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast)) < 0)
    {
        perror("broadcast options");
        closesocket(sock);
        return 1;
    }
    struct sockaddr_in Recv_addr;
    struct sockaddr_in Sender_addr;
    int len = sizeof(struct sockaddr_in);
    char recvBuff[50];
    int recvBuffLen = 50;
    //char sendMsg[] = "broadcast message from salam rofl";

    Recv_addr.sin_family = AF_INET;
    Recv_addr.sin_port = htons(PORT);
    Recv_addr.sin_addr.s_addr = INADDR_ANY;

    if(bind(sock, (sockaddr*)&Recv_addr, sizeof(Recv_addr)) < 0)
    {
        perror("bind");
        _getch;
        closesocket(sock);
        return 1;
    }

    //recvfrom(sock, recvBuff, recvBuffLen, 0, (sockaddr *)&Sender_addr, &len);
    //cout << "\nreceived message: " << recvBuff;

    while(1)
    {
        Sleep(3000);


        //_getch();

        getTime();
        if(sendto(sock, currentTime, strlen(currentTime)+1, 0, (sockaddr *)&Sender_addr, sizeof(Sender_addr)) < 0)
        {
            perror("borhot send: ");
            _getch();
            closesocket(sock);
            return 0;
        }
        else cout << "message sent successfully";
    }

    _getch;
    closesocket(sock);
    WSACleanup();
    return 0;

basically if I remove recvfrom, it will give me a send error ("No error") which simply puzzles me. also, if I send it something with a client, it will start broadcasting, but if I connect with another client, only the first client is receiving the broadcast.

thank you in advance. I doubt it matters but I'm trying to broadcast the current time.

icarus
  • 166
  • 1
  • 6
  • 14

2 Answers2

3

You are not initializing Sender_Addr so you are not telling sendto() where to actually broadcast to.

Try this instead:

WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);

SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == INVALID_SOCKET)
{
    perror("socket creation");
    _getch;
    return 1;
}

BOOL enabled = TRUE;
if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&enabled, sizeof(BOOL)) < 0)
{
    perror("broadcast options");
    _getch;
    closesocket(sock);
    return 1;
}

struct sockaddr_in Sender_addr;
Sender_addr.sin_family = AF_INET;
Sender_addr.sin_port = htons(BROADCAST_PORT);
Sender_addr.sin_addr.s_addr = inet_addr("Broadcast IP Here");

struct sockaddr_in Recv_addr;
Recv_addr.sin_family = AF_INET;
Recv_addr.sin_port = htons(PORT);
Recv_addr.sin_addr.s_addr = INADDR_ANY;

if (bind(sock, (sockaddr*)&Recv_addr, sizeof(Recv_addr)) < 0)
{
    perror("bind");
    _getch;
    closesocket(sock);
    return 1;
}

while(1)
{
    Sleep(3000);

    getTime();
    if (sendto(sock, currentTime, strlen(currentTime)+1, 0, (sockaddr *)&Sender_addr, sizeof(Sender_addr)) < 0)
    {
        perror("borhot send: ");
        _getch();
        closesocket(sock);
        return 0;
    }

    cout << "message sent successfully";
}

_getch;
closesocket(sock);

WSACleanup();
return 0;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • `Sender_addr.sin_addr.s_addr = inet_addr("Broadcast IP Here");` is a little confusing to me. You're setting the senders address to broadcast ip? What is this address? Let's say I'm on 10.0.0.x, should it say 10.0.0.255? – birgersp Jul 05 '16 at 16:13
  • 3
    `Sender_addr` is the *destination* address where data is to be broadcasted at. I'm simply using the same variable names that are in the OP's original code. `Sender_addr` could be renamed as `Send_addr` or `Target_addr` or `Broadcast_addr` or whatever makes more sense to you. The *sender's* address is the IP of the adapter that actually performs the broadcast. Since the socket is locally bound to `INADDR_ANY`, it is whichever adapter can reach the network that the broadcast IP belongs to. `10.0.0.255` would be the broadcast IP of your `10.0.0.x` network if its subnet mask is `255.255.255.0`. – Remy Lebeau Jul 05 '16 at 17:25
  • 1
    Use `GetAdaptersInfo()` or `GetAdaptersAddresses()` to get/calculate the actual broadcast IPs of your network adapters. – Remy Lebeau Jul 05 '16 at 17:30
  • Ah, I see. Thank you. – birgersp Jul 05 '16 at 17:51
2

Looks like your Sender_addr is never being initialized, thus when you remove the recvfrom you're getting an error, and when the recvfrom is in place it's getting populated with the address of the first client to connect (but never being updated).

If you don't know the addresses of the clients that you want to broadcast to, you'll need to setup some handshake where they send you a ping, you receive it with recvfrom, and you store their address in a list or something. Then, when you broadcast, you need to send your message to every client address in the list.

ryanbwork
  • 2,123
  • 12
  • 12
  • Or just initialize `Sender_addr` with the broadcast IP of the subnet, which is what the OP should be doing in the first place or else enabling SO_BROADCAST is useless. – Remy Lebeau Jun 07 '13 at 00:02