trying to broadcast through udp socket

2019-08-09 11:07发布

问题:

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.

回答1:

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.



回答2:

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;