soloforce 发表于 2014-10-5 08:53:43

利用广播获取CB的IP地址

本帖最后由 soloforce 于 2014-10-6 19:30 编辑

对于无显示器CB Linux系统,且IP地址为动态获取方式时,获取CB系统的IP地址可能是一个令人头疼的问题;然而利用局域网广播方法,则可以让与CB系统位于同一个局域网的其他机器得到CB系统的IP地址,仅仅需要Linux下socket编程的一些知识以及若干行代码。此外,为了适合各种类型的局域网,采用255.255.255.255的广播地址;当然,广播包不会被路由器转发。
===== CB系统代码 =====

/* filename: brdip.c
*
* IP broadcast via UDP
* by soloforce, 2014
*/

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

#define PORT 7777
#define MAXDATASIZE 256

int main(int argc,char *argv[])
{
    int socket_fd;
    struct sockaddr_in my_addr,user_addr;
    char buf;
    int so_broadcast=1;
    socklen_t size;
    char my_ip;
    my_addr.sin_family=AF_INET;
    my_addr.sin_port=htons(PORT);
    my_addr.sin_addr.s_addr=inet_addr("255.255.255.255");
    bzero(&(my_addr.sin_zero),8);

    user_addr.sin_family=AF_INET;
    user_addr.sin_port=htons(PORT);
    user_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    bzero(&(user_addr.sin_zero),8);
    if((socket_fd=(socket(AF_INET,SOCK_DGRAM,0)))==-1) {
      perror("socket");
      exit(1);
    }
    setsockopt(socket_fd,SOL_SOCKET,SO_BROADCAST,&so_broadcast,sizeof(so_broadcast));
    if((bind(socket_fd,(struct sockaddr *)&user_addr,
                        sizeof(struct sockaddr)))==-1) {
      perror("bind");
      exit(1);
    }

    // broadcast a message
    strcpy(buf,"Cubieboard on line!");
    sendto(socket_fd,buf,strlen(buf),0,(struct sockaddr *)&my_addr,sizeof(my_addr));

    // receive the message broadcast just now, to get user_addr which contains the IP info.
    size=sizeof(user_addr);
    recvfrom(socket_fd,buf,MAXDATASIZE,0,(struct sockaddr *)&user_addr,&size);

    // extract the IP info
    bzero(buf, sizeof(buf));
    sprintf(buf, "Cubieboard IP: %s\n",inet_ntoa(user_addr.sin_addr));

    // keep broadcast the IP info in 3 secs.
    while(1) {
      sendto(socket_fd,buf,strlen(buf),0,(struct sockaddr *)&my_addr,sizeof(my_addr));
      sleep(3);
    }
    return 0;
}
===== 客户机(Linux系统)代码 =====
/* filename: udprecv.c
*
* receive IP info via UDP
* by soloforce, 2014
*/

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

#define PORT 7777
#define MAXDATASIZE 256

int main(int argc, char**argv)
{
   int sockfd,n;
   struct sockaddr_in servaddr,cliaddr;
   socklen_t size;
   char buf;

   sockfd=socket(AF_INET,SOCK_DGRAM,0);
   bzero(&servaddr,sizeof(servaddr));
   servaddr.sin_family = AF_INET;
   servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
   servaddr.sin_port=htons(PORT);
   bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));

   while(1){
      size = sizeof(cliaddr);
      bzero(buf, sizeof(buf));
      n = recvfrom(sockfd,buf,1000,0,(struct sockaddr *)&cliaddr,&size);
      buf = 0;
      printf("%s",buf);
   }
}

===== 编译与执行 =====
分别在CB系统和客户系统中编译程序
CB $ gcc brdip.c -o brdip
GUEST $ gcc udprecv.c -o udprecv
分别执行之
CB $ ./brdip
GUEST $ ./udprecv
在客户系统中可以看到如下显示

Cubieboard IP: 192.168.1.124

Cubieboard IP: 192.168.1.124

Cubieboard IP: 192.168.1.124

Cubieboard IP: 192.168.1.124

Cubieboard IP: 192.168.1.124

Cubieboard IP: 192.168.1.124

Cubieboard IP: 192.168.1.124

Cubieboard IP: 192.168.1.124

Cubieboard IP: 192.168.1.124

Cubieboard IP: 192.168.1.124
...


jerryli 发表于 2014-10-5 15:24:34

本帖最后由 jerryli 于 2014-10-5 15:29 编辑

其实真的不要用那么麻烦。

我是这样做的,一般CT或者CB都是放在局域网用的,内网的出口一般就是路由器。

所以你只需要把CB接入网络,然后登录到路由器上看DHCP列表,路由器在分配IP后能看到已经连接主机,你找对应的host名称就行了(如果你是用默认的host没有修改过,一般一眼都能看出来是哪台)。

------------------
找到主机的IP后,下一步你就需要在路由器的DHCP上配置绑定MAC地址固定IP,这样每次你的这个设备联入这个网络的时候,IP地址就不会改变了。

soloforce 发表于 2014-10-5 17:10:35

jerryli 发表于 2014-10-5 15:24 static/image/common/back.gif
其实真的不要用那么麻烦。

我是这样做的,一般CT或者CB都是放在局域网用的,内网的出口一般就是路由器。


你说的对。直接到路由器查阅IP,或者根据MAC绑定IP,或者直接设置成静态IP,或者搬来一个显示器,或者用TTL线看……即使已经有100种办法了,多一种办法仍旧是好事 :)

醉月 发表于 2014-10-5 19:11:51

估计折腾CB的就两类人,一类是不会丁点编程,不懂linux的人;一类是程序员。
楼上两位的方法,分别适合这两类人。

如果是新手的话,补充下LZ的问题:LZ的这个小程序,还要想办法把这个小程序添加到 linux的开机启动项,具体百度和google都有很多方法

我这里也有另外一份代码分享下,效果是一样的:
https://github.com/boyisgood86/learning/blob/master/getlocalip.c

soloforce 发表于 2014-10-5 21:44:21

醉月 发表于 2014-10-5 19:11 static/image/common/back.gif
估计折腾CB的就两类人,一类是不会丁点编程,不懂linux的人;一类是程序员。
楼上两位的方法,分别适合这两 ...

补充的好! 抛砖引出玉了,hoho :)

webyxm 发表于 2014-10-6 10:47:38

又多了一种方法!一般我只直接查阅DHCP列表的。呵呵!这玩意真是折腾死人啊,其乐无穷啊!

soloforce 发表于 2014-10-6 19:34:33

其实这种方法的初衷是用在一个自定制的CB Linux 上, 无显示器, 无TTL,IP是动态获取的,那么这时就可以通过广播方式告知位于同一子网的其他客户机; 如果对安全有要求的用户,可以考虑把报文经过OPENSSL加密后发送,客户端预先装好了证书,即可保证信息安全。

cqOzil 发表于 2014-10-8 10:39:25

谢谢soloforce的分享,有用!自动获取地址后,准备用于自动更新box里面的内容。
另外之前只想到配置固定ip,居然没想到绑定mac,也谢谢jerryli。

PeterW 发表于 2014-11-10 17:52:37

我是安裝 sudo apt-get install samba , 用 PC Ping CB2 的 Hostname 就可以了 !!

但是 CB2 互相 Ping 則無法解譯名稱 !!

不知道用這方法好不好 ?

雁天翔 发表于 2015-10-23 20:03:32

感谢各位的讨论,受教了。
页: [1]
查看完整版本: 利用广播获取CB的IP地址