UDP:客户端发送广播,收到的IP不是服务器IP的问题

跟着《UNIX网络编程》书上的例程写了一个UDP广播的例子,接收到的服务器IP随机变化,最终发现recvfrom();最后一个参数在传递之前必须赋值 from_len = sizeof(struct sockaddr);否则接收到的对方地址不全!

下面代码

server.c:

#include <netinet/in.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/select.h>
#include <time.h>

#define IP_FOUND "IP_FOUND"
#define IP_FOUND_ACK "IP_FOUND_ACK"
#define MAST_PORT 8888

void main(void *arg)
{
 #define BUFFER_LEN 32
 int ret = -1;
 int sock = -1;
 struct sockaddr_in local_addr;
 struct sockaddr_in from_addr;
 int from_len;
 int count = -1;
 fd_set readfds;
 char buff[BUFFER_LEN] = {0};
 struct timeval timeout;
 timeout.tv_sec = 2;
 timeout.tv_usec = 0;

 printf("====>HandleIPFound\n");

 sock = socket(AF_INET, SOCK_DGRAM, 0);
 if(sock < 0)
 {
  printf("HandleIPFound: sock init error\n");
  return;
 }

 
 int reuse = 1;
 if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1)
 {
  return;
 }

 bzero(&local_addr, sizeof(local_addr));

 local_addr.sin_family = AF_INET;
 local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
 local_addr.sin_port = htons(MAST_PORT);

 ret = bind(sock, (struct sockaddr *)&local_addr, sizeof(local_addr));
 if(ret != 0)
 {
  printf("HandleIPFound: bind error\n");
  return;
 }

 while(1)
 {
  FD_ZERO(&readfds);
  FD_SET(sock, &readfds);

  timeout.tv_sec = 2;
  timeout.tv_usec = 0;

  ret = select(sock + 1, &readfds, NULL, NULL, &timeout);
  switch (ret)
  {
   case -1:
    break;
   case 0:
    printf("timeout\n");
    break;
   default:
    if(FD_ISSET(sock, &readfds))
    {
     from_len = sizeof(from_addr);
     count = recvfrom(sock, buff, BUFFER_LEN, 0, (struct
      sockaddr *)&from_addr, &from_len);
     printf("Recv msg is %s\n", buff);

     if(strstr(buff, IP_FOUND))
     {
      memcpy(buff, IP_FOUND_ACK, strlen(IP_FOUND_ACK) + 1);
      printf("send msg to client\n");
      from_len = sizeof(from_addr);
      count = sendto(sock, buff, strlen(buff), 0, (struct sockaddr*)&from_addr, from_len);
     }
     else
     {
      printf("not equal with IP_FOUND\n");
     }
    }
  }
 }
 printf("<===HandleIPFound\n");
 return;
}

client.c

#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/select.h>
#include <time.h>
#include <errno.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>

#define IP_FOUND "IP_FOUND"
#define IP_FOUND_ACK "IP_FOUND_ACK"
#define IFNAME "eth0"
#define MCAST_PORT 8888

void main(void *arg)
{
 #define BUFFER_LEN 32
 int ret = -1;
 int sock = -1;
 int so_broadcast = 1;
 struct ifreq ifr;
 struct sockaddr_in broadcast_addr;
 struct sockaddr_in from_addr;
 int from_len;
 int count = -1;
 fd_set readfd;
 char buff[BUFFER_LEN] = {0};
 struct timeval timeout;
 timeout.tv_sec = 20;
 timeout.tv_usec = 0;

 sock = socket(AF_INET, SOCK_DGRAM, 0);
 if(sock < 0)
 {
  printf("HandleIPFound: socket init error\n");
  return;
 }
 strcpy(ifr.ifr_name, IFNAME);
 if(ioctl(sock, SIOCGIFBRDADDR, &ifr) == -1)
  perror("ioctl error"), exit(1);
 memcpy(&broadcast_addr, &ifr.ifr_broadaddr, sizeof(struct sockaddr_in));
 broadcast_addr.sin_port = htons(MCAST_PORT);

 ret = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &so_broadcast,
  sizeof(so_broadcast));

 int times = 10;
 int i = 0;
 for(i = 0; i < times; i++)
 {
  ret = sendto(sock, IP_FOUND, strlen(IP_FOUND), 0, (struct sockaddr*)
   &broadcast_addr, sizeof(broadcast_addr));
  if(ret == -1)
  {
   continue;
  }

  FD_ZERO(&readfd);
  FD_SET(sock, &readfd);
  timeout.tv_sec = 10;
  timeout.tv_usec = 0;
  ret = select(sock + 1, &readfd, NULL, NULL, &timeout);
  switch(ret)
  {
   case -1:
    break;
   case 0:
    printf("time out\n");
    break;
   default:
    if(FD_ISSET(sock, &readfd))
    {
     from_len = sizeof(from_addr);
     count = recvfrom(sock, buff, BUFFER_LEN, 0, (struct sockaddr*)&from_addr, &from_len);
     printf("Client Recv msg is %s\n", buff);
     if(strstr(buff, IP_FOUND_ACK))
     {
      printf("Client found server, IP is %s\n", inet_ntoa(from_addr.sin_addr));
      break;
     }
    }
  }
 }
 return;
}

 

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值