2016-04-06 110 views
0

對於一個項目,我需要每秒發送一次UDP廣播到87.255.255.255和端口4448與我的項目的值。我已經writen在C++中的一些代碼,但我得到總是錯誤:C++發送UDP廣播

斷言`::綁定(S,(SOCKADDR *)& si_me,的sizeof(SOCKADDR))= - 1' 失敗

與此行:

//assert(::bind(s, (sockaddr *)&si_me, sizeof(sockaddr))!=-1); 

當我刪除這行代碼運行,但我找不到wireshark。

有沒有人有解決方案或一些額外的信息來建立一個廣播發送者?

#include <stdio.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <netdb.h> 
#include <assert.h> 
#include <string.h> 
#include <ctime> 

int main(int argc, char const *argv[]) { 

    sockaddr_in si_me, si_other; 
    int s; 
    printf("Making socket\n"); 
    assert((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))!=-1); 
    fprintf(stderr,"usage %s hostname port\n", argv[0]); 
    int port=4448; 
    int broadcast=1; 
    setsockopt(s, SOL_SOCKET, SO_BROADCAST, 
     &broadcast, sizeof broadcast); 

     memset(&si_me, 0, sizeof(si_me)); 
     si_me.sin_family = AF_INET; 
     si_me.sin_port = htons(port); 
     si_me.sin_addr.s_addr = INADDR_ANY; 

    assert(::bind(s, (sockaddr *)&si_me, sizeof(sockaddr))!=-1); 

    while(1) 
    { 
    printf("Send message to broadcast\n"); 
    char buf[10000]; 
    strcpy(buf, "test for wireshark"); 
    unsigned slen=sizeof(sockaddr); 
    send(s, buf, sizeof(buf)-1, 0); 
    //recvfrom(s, buf, sizeof(buf)-1, 0, (sockaddr *)&si_other, &slen); 
    printf("recv: %s\n", buf); 
    sleep(1); 
    } 
} 
+0

將函數包裝在'assert()'中通常是一個壞主意,因爲在調試關閉時它們將被刪除。而不是_asserting_調用'perror()',這樣你就可以看到它失敗的原因。 –

+0

我嘗試將其更改爲perror,但我得到了錯誤:無法將'bool'轉換爲'const char *'作爲參數'1'到'void perror(const char *)' – josejos41

+0

if(bind(...) <0)perror(「bind()」);'而不是'assert(bind(...)!= - 1);' –

回答

0

顯然在UNIX下廣播有一些奇怪之處。所以這可能會或可能不會按預期工作。

void errno_abort(const char* header) 
{ 
    perror(header); 
    exit(EXIT_FAILURE); 
} 

int main(int argc, char* argv[]) 
{ 
#define SERVERPORT 4567 
    struct sockaddr_in send_addr, recv_addr; 
    int trueflag = 1, count = 0; 
    int fd; 
    if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 
     errno_abort("socket"); 
#ifndef RECV_ONLY 
    if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, 
        &trueflag, sizeof trueflag) < 0) 
     errno_abort("setsockopt"); 

    memset(&send_addr, 0, sizeof send_addr); 
    send_addr.sin_family = AF_INET; 
    send_addr.sin_port = (in_port_t) htons(SERVERPORT); 
    // broadcasting address for unix (?) 
    inet_aton("127.255.255.255", &send_addr.sin_addr); 
    // send_addr.sin_addr.s_addr = htonl(INADDR_BROADCAST); 
#endif // ! RECV_ONLY 

#ifndef SEND_ONLY 
    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 
        &trueflag, sizeof trueflag) < 0) 
     errno_abort("setsockopt"); 

    memset(&recv_addr, 0, sizeof recv_addr); 
    recv_addr.sin_family = AF_INET; 
    recv_addr.sin_port = (in_port_t) htons(SERVERPORT); 
    recv_addr.sin_addr.s_addr = htonl(INADDR_ANY); 

    if (bind(fd, (struct sockaddr*) &recv_addr, sizeof recv_addr) < 0) 
     errno_abort("bind"); 
#endif // ! SEND_ONLY 

    while (1) { 
#ifndef RECV_ONLY 
     char sbuf[256] = {}; 
     snprintf(sbuf, sizeof(sbuf), "Hello(%d)!", count++); 
     if (sendto(fd, sbuf, strlen(sbuf)+1, 0, 
        (struct sockaddr*) &send_addr, sizeof send_addr) < 0) 
      errno_abort("send"); 
     printf("send: %s\n", sbuf); 
     usleep(1000000/2); 
#endif // ! RECV_ONLY 

#ifndef SEND_ONLY 
     char rbuf[256] = {}; 
     if (recv(fd, rbuf, sizeof(rbuf)-1, 0) < 0) 
      errno_abort("recv"); 
     printf("recv: %s\n", rbuf); 
#endif // ! SEND_ONLY 
    } 
    close(fd); 
    return 0; 
} 

希望這會有所幫助。祝你好運。

0

發送一個大小爲10000的UDP數據包可能是一個壞主意。 嘗試使用strlen(緩衝區),而不是在調用send()時。這可能是你在鯊魚身上看不到任何東西的原因。

要找到bind()失敗的原因,您需要評估errno。

BTW:我記得有一個TCP堆棧實現,它不像IPPROTO_UDP那樣作爲socket()調用的第三個參數,即使它應該按照標準工作。嘗試使用0代替。

+0

我已經將緩衝區更改爲20.除了我必須刪除斷言行以編譯它外,什麼都不做。 – josejos41

+0

我已將IPPROTO_UDP更改爲零,但我沒有看到wireshark上傳遞的任何內容。 – josejos41