2017-06-01 55 views
0

爲什麼這個單播沒有被客戶端接收到?我幾個小時一直在嘲笑這件事。 GRR ..;(爲什麼這個UDP單播沒有被客戶端接收到?

  • 我送的價格蜱形式nn.dd;例如,42.23,93.75僅有5個字節用於測試目的
  • 服務器的(打勾發生器)的IP地址爲192.168。 .1.101
  • 客戶端的地址是192.168.1.102
  • sendto命令的返回值是5,因爲它應該是
  • 我可以ping通在兩個方向:從服務器的客戶端,並從客戶端服務器;約3毫秒的響應時間。
  • 兩臺機器都在同一個網絡上。被生成併發送到
  • 價格如下所示
  • 在同一臺機器上客戶端進程,(帶192.168.1.101的相同的IP地址)以不同的終端,能正常工作,如示於下段2 。
  • 完整的代碼包含在片段3和4
  • 的Linksys WRT54GL V1.1與股票BIOS
  • 此代碼是Beej的UDP例的修改後的版本在這裏: http://beej.us/guide/bgnet/output/html/multipage/clientserver.html#datagram
  • 注:與tickGenerator 192.168.1.101 helloWorld啓動服務器(當然使用你的IP地址)。 Beej的例子中的「helloWorld」將被忽略;我在隨機價格生成器中進行了黑客攻擊。

蜱發生器輸出:正確地從192.168.1.101生成蜱數據:在單獨的終端窗口

Price unicasted: 49.58 
Price unicasted: 50.00 
Price unicasted: 50.24 
... 

客戶端在同一臺機器(也從192.168.1.101)上正確接收到組播:

listener: waiting to recvfrom... 
listener: got packet from 192.168.1.101 
listener: packet is 5 bytes long 
listener: packet contains "49.58" 
listener: got packet from 192.168.1.101 
listener: packet is 5 bytes long 
listener: packet contains "50.00" 
listener: got packet from 192.168.1.101 
listener: packet is 5 bytes long 
listener: packet contains "50.24" 
... 

在192.168.1.102單獨的機器只是掛...

蜱發生器:

/* 
** talker.c -- a datagram "client" demo 
*/ 

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <errno.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <netdb.h> 

#include <time.h> 
#include <stdlib.h> 
#include <math.h> 
#include <chrono> 
#include <thread> 
#include <iostream> 

#define SERVERPORT "4950" // the port users will be connecting to 

void reverse(char *str, int len) { 
    int i=0, j=len-1, temp; 
    while (i<j) 
    { 
     temp = str[i]; 
     str[i] = str[j]; 
     str[j] = temp; 
     i++; j--; 
    } 
} 
int intToStr(int x, char str[], int d) 
{ 
    int i = 0; 
    while (x) { 
     str[i++] = (x%10) + '0'; 
     x = x/10; 
    } 
    while (i < d) 
     str[i++] = '0'; 

    reverse(str, i); 
    str[i] = '\0'; 
    return i; 
} 
void ftoa(float n, char *res, int afterpoint) { 
    int ipart = (int)n; 
    float fpart = n - (float)ipart; 
    int i = intToStr(ipart, res, 0); 
    if (afterpoint != 0) { 
     res[i] = '.'; 
     fpart = fpart * 100; 
     intToStr((int)fpart, res + i + 1, afterpoint); 
    } 
} 
float randPrice() { 
    int b; 
    float d; 
    b = 4950 + rand() % 100 + 1; 
    d = (float)b/100; 
    return d; 
} 
int main(int argc, char *argv[]) 
{ 
    int sockfd; 
    struct addrinfo hints, *servinfo, *p; 
    int rv; 
    int numbytes; 

    if (argc != 3) { 
     fprintf(stderr,"usage: talker hostname message\n"); 
     exit(1); 
    } 

    memset(&hints, 0, sizeof hints); 
    hints.ai_family = AF_UNSPEC; 
    hints.ai_socktype = SOCK_DGRAM; 

    if ((rv = getaddrinfo(argv[1], SERVERPORT, &hints, &servinfo)) != 0) { 
     fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); 
     return 1; 
    } 

    // loop through all the results and make a socket 
    for(p = servinfo; p != NULL; p = p->ai_next) { 
     if ((sockfd = socket(p->ai_family, p->ai_socktype, 
          p->ai_protocol)) == -1) { 
      perror("talker: socket"); 
      continue; 
     } 

     break; 
    } 

    if (p == NULL) { 
     fprintf(stderr, "talker: failed to create socket\n"); 
     return 2; 
    } 

    char myPrice[6]; 
    float f; 

    while(1) { 
     f = randPrice(); 
     ftoa(f, myPrice, 2); // Convert price to string 
     std::cout << "Price multicasted: " << myPrice << std::endl; 
     if ((numbytes = sendto(sockfd, myPrice, strlen(myPrice), 0, p->ai_addr, p->ai_addrlen)) == -1) { 
      perror("talker: sendto"); 
      exit(1); 
     } 
     std::this_thread::sleep_for(std::chrono::milliseconds(1000)); 
    } 

    freeaddrinfo(servinfo); 

    printf("talker: sent %d bytes to %s\n", numbytes, argv[1]); 
    close(sockfd); 

    return 0; 
} 

蜱監聽器:

/* 
** listener.c -- a datagram sockets "server" demo 
*/ 

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <errno.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <netdb.h> 

#define MYPORT "4950" // the port users will be connecting to 

#define MAXBUFLEN 100 

// get sockaddr, IPv4 or IPv6: 
void *get_in_addr(struct sockaddr *sa) 
{ 
    if (sa->sa_family == AF_INET) { 
     return &(((struct sockaddr_in*)sa)->sin_addr); 
    } 

    return &(((struct sockaddr_in6*)sa)->sin6_addr); 
} 

int main(void) 
{ 
    int sockfd; 
    struct addrinfo hints, *servinfo, *p; 
    int rv; 
    int numbytes; 
    struct sockaddr_storage their_addr; 
    char buf[MAXBUFLEN]; 
    socklen_t addr_len; 
    char s[INET6_ADDRSTRLEN]; 

    memset(&hints, 0, sizeof hints); 
    hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4 
    hints.ai_socktype = SOCK_DGRAM; 
    hints.ai_flags = AI_PASSIVE; // use my IP 

    if ((rv = getaddrinfo(NULL, MYPORT, &hints, &servinfo)) != 0) { 
     fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); 
     return 1; 
    } 

    // loop through all the results and bind to the first we can 
    for(p = servinfo; p != NULL; p = p->ai_next) { 
     if ((sockfd = socket(p->ai_family, p->ai_socktype, 
          p->ai_protocol)) == -1) { 
      perror("listener: socket"); 
      continue; 
     } 

     if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) { 
      close(sockfd); 
      perror("listener: bind"); 
      continue; 
     } 

     break; 
    } 

    if (p == NULL) { 
     fprintf(stderr, "listener: failed to bind socket\n"); 
     return 2; 
    } 

    freeaddrinfo(servinfo); 

    printf("listener: waiting to recvfrom...\n"); 

    addr_len = sizeof their_addr; 

    while(1) { 
     if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN-1 , 0, 
           (struct sockaddr *)&their_addr, &addr_len)) == -1) { 
      perror("recvfrom"); 
      exit(1); 
     } 

     printf("listener: got packet from %s\n", 
       inet_ntop(their_addr.ss_family, 
         get_in_addr((struct sockaddr *)&their_addr), 
         s, sizeof s)); 
     printf("listener: packet is %d bytes long\n", numbytes); 
     buf[numbytes] = '\0'; 
     printf("listener: packet contains \"%s\"\n", buf); 
    } 

    close(sockfd); 

    return 0; 
} 
+0

也許您的網絡交換機不支持多播轉發? – Barmar

+0

我沒有看到在這裏使用多播的任何嘗試。你打電話給發件人的確切程度如何?另外,你能夠在兩臺機器之間發送單播嗎? – dbush

+0

是的,好點;我的意思是UDP數據報;這實質上是一個單播。下一步是使其成爲一個組播,以便許多市場參與者可以訂閱數據饋送:)。更新。 – kmiklas

回答

0

的問題是在收聽該綁定。你應該綁定到INADDR_ANY而不是一個特定的IP地址。

查看發件人發送的實際IP地址也很有趣。

+0

請使用代碼示例編輯如何綁定到INADDR_ANY?我正在攀登一條學習曲線。另外,發送者正在發送到192.168.1.101;我把''argv [1]''的值打印到屏幕上。 – kmiklas

相關問題