我服务器放在景区镇上租的住处里,附近经常因为施工或是乱开挖之类的导致断电。我用的电信宽带。每次断电之后服务器自动重启就得重新分配一个ip。因为用了域名服务,重启后能根据域名查询到新的IP。

但是,我还是尝到了几次找不到服务器IP的苦头。有次在实验室通宵,准备连接上屋里的服务器做测试,因为以前觉得域名很方便就没有做记录IP的工作。结果就发现连不上了,打电话问住同一小区的朋友是不是停电了,结果根本就没有停电。登陆到我所使用的域名服务器的官网,才发现域名服务器瘫痪了,要维修两天。我特地买了大堆吃的到实验室准备利用两个不同的网络环境通宵做测试的,结果因为不知道服务器的IP,什么事情都做不了。自己有尝试用一些以前用过的IP去暴力连接,但都失败了。深更半夜的,想回去也没办法。于是开撸...

这种情况我遇上了很多次,但每次都没有办法。因为用的免费的域名服务,不可能给我多完善的服务。于是自己想办法解决这个问题。目前想了以下这几种办法:

1、使用2种以上不同的域名服务器。(该方法可行,服务器主机支持,路由器只支持某一个域名服务器)

2、使用一些手段通知自己更新后的IP。(正好我之前写过邮件服务器,可以通过这种方法,当我IP改变时或定时向我的一些邮箱发送服务器的当前IP,这方法不错,但是有些担心邮件发多了又要被那些小气的邮件服务器当成垃圾邮件把我拉黑。当我域名出现问题时,也通不过一些服务器的域名验证)

3、服务器上登个QQ。(哈哈,居然有这么NB的办法,而且真的很有用呢,IP是准的,QQ的服务器基本不会停机维护。但还是不完美,有时候登陆时间长了或是自动登陆失败后需要手动输入验证码,这就没辙了,因为PPPOE登陆实在路由器上,有时候服务器开机了路由器还没有登陆,就会出现QQ登陆不上的问题,这种情况设置下登陆延时应该就没问题了)

4、询问服务器所属网段类的所有IP地址。(因为无论怎么重新分配IP,他的大的网段都不会变的。我查了查,我那的地址始终是118.112-113.0.0的网段。)

对比之下,还是4这种自力更生的方法适合我,我直接做一个C/S结构的搜索程序就行了。2*256*256=131072。最多才十多万个可能的IP,分分钟就能找到我的服务器。设计的原理是:服务器这边始终监听着一个专用端口,用来接收客户端发过来的询问。如果询问信息和服务器最初设置的口令一致,服务器便向该地址回复同样的信息。客户端收到服务器相同的回复后,便能认定该地址就是要找的服务器IP地址。

因为改程序不需要占用太多资源,且需要跟着系统一起运行。我就直接在控制台实现,因为客户端需要像大量不同的IP发送信息,因此我使用非阻塞的UDP来进行通信。

以下是服务端的实现代码:

#include<windows.h>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<winsock.h>struct findinfo//发送的口令结构
{char name[32];
};findinfo minfo;
SOCKET ssock;
sockaddr_in saddr;
unsigned short sport;
HANDLE sthreadhandle;
bool isendthread;
UINT opthread(LPVOID Param);
//#pragma comment(lib,"ws2_32.lib")
using namespace std;bool init()//初始化口令信息与监听端口
{FILE *f;if(!(f=fopen("findinfo","r")))//初始化信息储存在文件findinfo中{puts("not find init file");return false;}fscanf(f,"%s%d",minfo.name,&sport);if(strlen(minfo.name)<1){puts("init file error");return false;}printf("token:%s\nsport:%d\n",minfo.name,sport);fclose(f);return true;
}bool setreg()//设置开机启动
{char procbuf[256];GetModuleFileName(GetModuleHandle(NULL),procbuf,sizeof(procbuf));printf("this proc at:%s\n",procbuf);HKEY key;int ret;ret=RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",0,KEY_SET_VALUE,&key);if(ret!=0){printf("regopenkey fail:%d\n",ret);return false;}ret=RegSetValueEx(key,"findipsever",0,REG_SZ,(const unsigned char*)procbuf,sizeof(procbuf));if(ret!=0){printf("set reginfo fail:%d\n",ret);ret=RegCloseKey(key);return false;}ret=RegCloseKey(key);return true;
}
bool clearreg()//清除开机启动
{char procbuf[256];GetModuleFileName(GetModuleHandle(NULL),procbuf,sizeof(procbuf));printf("this proc at:%s\n",procbuf);HKEY key;int ret;ret=RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",0,KEY_SET_VALUE,&key);if(ret!=0){printf("regopenkey fail:%d\n",ret);return false;}RegDeleteValue(key,"findipsever");if(ret!=0){printf("clear reginfo fail:%d\n",ret);ret=RegCloseKey(key);return false;}ret=RegCloseKey(key);return true;
}
int main(int argv,char* argc[])
{if(argv>1)//配置开机启动{if(argc[1][0]=='-'&&argc[1][1]=='s'){if(setreg()){puts("set reg secc");}else{puts("set reg fail");}return 0;}if(argc[1][0]=='-'&&argc[1][1]=='c'){if(clearreg()){puts("clear reg secc");}else{puts("clear reg fail");}return 0;}}if(argv>2)//配置口令和端口信息{FILE *f;if(!(f=fopen("findinfo","w+"))){puts("can't open init file");return -1;}fprintf(f,"%s\n%s",argc[1],argc[2]);fclose(f);printf("edit:%s %s  secc\n",argc[1],argc[2]);return 0;}if(!init())//初始化口令和端口信息{puts("init error");return -1;}WSADATA wsaData;if(WSAStartup(MAKEWORD(1,0),&wsaData)){printf("start socket error\n");return -1;}ssock=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);//套接字使用UDPif(ssock==INVALID_SOCKET){printf("create sock error\n");WSACleanup();return -1;}saddr.sin_family = AF_INET;saddr.sin_port= htons(sport);//设置为所配置的端口saddr.sin_addr.S_un.S_addr = INADDR_ANY;if(bind(ssock,(sockaddr *)&saddr,sizeof(sockaddr))==SOCKET_ERROR){printf("bind error\n");WSACleanup();return -1;}sockaddr_in newaddr;int addrsize=sizeof(sockaddr);char *buf=new char[256];int buflen;findinfo *reinfo=new findinfo;//设置为非阻塞模式int iMode=1;ioctlsocket(ssock,FIONBIO,(u_long FAR*)&iMode);isendthread=false;puts("--------sever start---------");//开启控制线程sthreadhandle=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)opthread,NULL,0,NULL);while(!isendthread)//循环监听{buflen=recvfrom(ssock,buf,200,0,(sockaddr *)&newaddr,&addrsize);if(buflen>0){buf[buflen]='\0';//puts(buf);reinfo=(findinfo *)buf;if(strcmp(minfo.name,reinfo->name)==0)//口令匹配成功后进行回复{printf("%s send an request\n",inet_ntoa(newaddr.sin_addr));sendto(ssock,(char *)&minfo,sizeof(minfo),0,(sockaddr *)&newaddr,sizeof(sockaddr));}}Sleep(100);//休眠节约资源}puts("---------sever end----------");Sleep(500);puts("---------main exit----------");return 0;
}UINT opthread(LPVOID Param)//控制线程
{puts("-----enter hide window------");//getchar();Sleep(20000);HWND dos=GetForegroundWindow();ShowWindow(dos,SW_HIDE);puts("------ernter end sever------");getchar();isendthread=true;return 0;
}

对我那台服务器而言,客户端最多只需要发送10万条询问即可完成查询,就当客户端的上行带宽是1M,一条询问最多0.1k,不计网卡的的处理速度的话,最多2分钟就能完成询问。考虑到网卡的处理速度以及上行带宽。客户端进行查询就只使用一条线程进行发送询问,一条接收回复。代码如下:

#include<windows.h>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<winsock.h>using namespace std;struct findinfo//发送的口令结构
{char name[32];
};char resultip[512][20];//储存获取到的服务器恢复结果(考虑广播地址发送至目的地的回复)
int resultnum;findinfo minfo;
SOCKET sock;
sockaddr_in saddr;
HANDLE sthreadhandle;
bool isendthread;
UINT opthread(LPVOID Param);bool isipend(unsigned short *s1,unsigned short *s2)//判断查询的IP是否越界
{for(int i=0;i<4;i++){if(s1[i]<s2[i]){return false;}}return true;
}int main(int argv,char* argc[])
{if(argv<2){puts("format error\nthe right format: token port? startip? endip?");exit(-1);}strcpy(minfo.name,argc[1]);unsigned port=998;unsigned short sip[5];unsigned short eip[5];//查询至少带有口令参数,缺省:端口 开始ip 结束ip//默认:998端口 0.0.0.0-255.255.255.255if(argv>2){port=atoi(argc[2]);}if(argv>3){sscanf(argc[3],"%u.%u.%u.%u",sip,sip+1,sip+2,sip+3);//printf("%s %u %u %u %u\n",argc[3],sip[0],sip[1],sip[2],sip[3]);}else{for(int i=0;i<4;i++){sip[i]=0;}}if(argv>4){sscanf(argc[4],"%u.%u.%u.%u",eip,eip+1,eip+2,eip+3);}else{for(int i=0;i<4;i++){eip[i]=255;}}WSADATA wsaData;if(WSAStartup(MAKEWORD(1,0),&wsaData)){printf("start socket error\n");return -1;}sock=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);//使用UDP套接字if(sock==INVALID_SOCKET){printf("create sock error\n");WSACleanup();return -1;}//设置UDP非阻塞int iMode=1;ioctlsocket(sock,FIONBIO,(u_long FAR*)&iMode);//开启接收应答线程sthreadhandle=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)opthread,NULL,0,NULL);saddr.sin_family = AF_INET;saddr.sin_port= htons(port);char cryip[20];int ret;/*saddr.sin_addr.S_un.S_addr = inet_addr("192.168.0.155");sendto(sock,(char *)&minfo,sizeof(minfo),0,(sockaddr *)&saddr,sizeof(sockaddr));*/puts("-----------start  find-------------");while(!isipend(sip,eip))//开始发送询问信息{sprintf(cryip,"%u.%u.%u.%u",sip[0],sip[1],sip[2],sip[3]);saddr.sin_addr.S_un.S_addr = inet_addr(cryip);ret=sendto(sock,(char *)&minfo,sizeof(minfo),0,(sockaddr *)&saddr,sizeof(sockaddr));if(ret==SOCKET_ERROR){Sleep(2000);continue;}//修改到下一个IPsip[3]++;for(int i=3;i>0;i--){if(sip[i]>255){sip[i]=0;sip[i-1]++;printf("now at: %s\n",cryip);}}}Sleep(2000);puts("--------send find info end---------");puts("-------enter check result----------");getchar();isendthread=true;Sleep(500);closesocket(sock);puts("------------main  exit--------------");return 0;
}UINT opthread(LPVOID Param)
{char *buf=new char[256];int buflen;findinfo *reinfo;sockaddr_in newaddr;int addrlen=sizeof(sockaddr);resultnum=0;isendthread=false;//printf("recvfrom start");while(!isendthread)//接收服务器的回复{buflen=recvfrom(sock,buf,200,0,(sockaddr *)&newaddr,&addrlen);if(buflen>0){buf[buflen]='\0';//puts(buf);reinfo=(findinfo *)buf;//如果接收到正确的回复,就将回复的IP地址存入结果字符串数组if(strcmp(minfo.name,reinfo->name)==0){strcpy(resultip[resultnum++],inet_ntoa(newaddr.sin_addr));printf("find an addr at: %s\n",resultip[resultnum-1]);}}//Sleep(100);}if(resultnum==0){puts("not find any ip");}else{for(int i=0;i<resultnum;i++){printf("find an addr at: %s\n",resultip[i]);}}/*getchar();isendthread=true;*/puts("--------recvfrom thread end--------");return 0;
}

下面看下使用效果:

服务器首先要配置口令和端口,直接带上口令和端口参数即可

服务器使用参数:-s 配置开机启动 -c清除开机启动

自己运行即可开始服务

客户端查询至少带有口令参数,缺省:端口 开始ip 结束ip。默认:998端口 0.0.0.0-255.255.255.255

例如我要查询口令上面的服务器,参数为:wchrt 998 118.112.0.0 118.113.255.255

如图:

程序开始逐个IP进行询问,我这的运行速度是每秒查询1000个左右

查询完毕,发现了服务器所在的IP地址:118.112.50.14.查询成功

源码

转载于:https://blog.51cto.com/wchrt/1608152

广播搜寻服务器的动态IP相关推荐

  1. wr885n虚拟服务器设置,动态IP设置:选择动态IP(以太网宽带

    tplink885n设置操作步骤如下 一台新购买(恢复出厂设置)的TL-WR885N路由器,要实现上网功能,需要进行下面3个步骤 :1.TL-WR885N路由器安装;2.设置电脑IP地址;3.TL-W ...

  2. 爬虫进阶——解决封IP问题| 部署ADSL服务器获取动态IP

    1.问题背景 我们公司需要到某环保平台爬取环保信息,但平台那边先从封cookie开始,后来又封IP,目前又开始封账号..本章就讲讲封IP问题的一个解决策略--部署ADSL服务器吧. ADSL服务器是什 ...

  3. zabbix如何监控ip地址_Zabbix主动模式监控动态IP服务器

    一.需求:服务器(Linux系统)使用的是动态IP(PPOE拨号,不定时更改IP),现在要求使用Zabbix监控服务器状态. 1,zabbix健康服务器设置: configuration-Templa ...

  4. 使用动态IP+MDaemon架设邮件服务器

    最近和几个朋友以前在捣鼓MDaemon,在慢慢看教程跟摸索的情况下,了解了MD最基本的一些应用,下面我们就一步一步来做,目标是建立一个能收发外网的拥有顶级域名的内部邮件服务器.像我这样的属于穷鬼一族, ...

  5. linux动态ip做服务器,在Linux实现基于动态IP的WWW服务器

    ZDNetChina服务器站 服务器操作系统技巧 基于动态ip的服务器同样可以开设www服务接受客户端的访问,这可以通过以下的脚本来实现.请先建立PPP连接,配置好Httpd,测试它可以工作. 建立如 ...

  6. 设置安装使用动态IP+MDaemon架设邮件服务器

    废话就不多说了,开始... 近最和几个友人前以在捣鼓MDaemon,在慢慢看程教跟探索的情况下,了解了MD最基本的一些应用,面上我们就一步一步来做,标目是建立一个能发收外网的有拥顶级名域的部内件邮务服 ...

  7. DHCP 实现动态 IP 上网简析

    首先,我们需要知道计算机是如何上网的. 计算机之间的通信是建立在五层架构上的,一台计算机要想实现与互联网中另外一台台计算机之间的通信,计算机至少需要知道下面四个参数: *本机的IP地址 *子网掩码 * ...

  8. 动态IP分配协议:DHCP

    文章目录 1. 什么是DHCP? 2. 为什么要使用DHCP? 3. DHCP是怎么工作的? 3.1 无中继场景时DHCP客户端首次接入网络的工作原理 第一步:发现阶段 第二步:提供阶段 第三步:选择 ...

  9. 网站服务器的ip地址会变吗,网站的服务器变了 IP地址变吗

    网站的服务器变了 IP地址变吗 内容精选 换一换 本文介绍通过华为云市场镜像"Drupal内容管理系统(LAMP)"搭建Drupal网站的方法.Drupal是使用PHP语言编写的开 ...

最新文章

  1. 多线程编程3 - NSOperationQueue
  2. mysql免安装数据库用法_MySQL数据库之mysql免安装制作使用说明
  3. Vue中的静态类型检查
  4. JavaWeb学习--Servlet认识
  5. Deepin Linux 设置开机自动进入命令行模式
  6. 利用注册表修改桌面背景
  7. ccccccccccccccccccccc
  8. android uboot boot 区别,uboot fastboot原理
  9. CCNA考试题库中英文翻译版及答案14
  10. python-网络编程-tcp/ip认识(一)
  11. python apply函数_Python中apply函数的用法实例教程
  12. 听说你要找前端工作,写一个酷炫的动画的简历呀
  13. 马赛克,一生之敌,是时候说再见了【兄弟,借一部说话】
  14. vim 重新编译,支持lua (compile vim with lua)
  15. Silicon EFR32BG22低功耗蓝牙开发入门篇
  16. linux查看当前运行的进程
  17. Code,Diagram and Model
  18. android5.0模拟器pc版,逍遥安卓独家发布支持5.0安卓系统电脑模拟器
  19. Ubuntu18.04添加自启动脚本
  20. android 退出app代码_PPT 下载 | APP 埋点那些事

热门文章

  1. React Nativi 参考文章
  2. php lyadmin,index.php
  3. controller调用controller的方法_SpringCloud Alibaba微服务实战三 - 服务调用
  4. python数据分析报告的格式_Python数据报表之Excel操作模块用法分析
  5. iphone全部机型_iPhone12卖爆 产业链喜迎5G时代 股价天花板打开?|iphone|iphone12|运营商|智能机...
  6. centos php 安装mysql_CentOS 7 安装MySQL+PHP环境
  7. 2个点马氏距离计算实例_数据分析基础:距离度量方式(欧式距离、马氏距离、曼哈顿距离)...
  8. Nuke编辑工具包新版 Cara VR 插件发布
  9. 2021年Python十佳ML库大盘点,国产选手GitHub半年获5k+star,第一名是升级版NumPy
  10. 日本搞出奇妙充电屋,坐在任意位置都能隔空充电!研究登上Nature子刊