2016-04-06 112 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