通过广播获取ip地址的实现
引言
在进行网络程序的设计时,有时候我们不想要手动指定接收方的ip尤其是在做聊天小程序的时候,因为这个时候对方的ip不是固定的,那么我们该怎么办呢?一个方法就是接收方创建一个socket监听一个端口,发送方通过广播的方式给所有局域网内的主机发送一个“hello”包,当然这个包是发往接收方监听的端口的,接收方接收到“hello”包后获取自己的ip地址然后封装在数据报里再发回给发送方,这样发送方就能获得局域网内所有在线的接收方的信息了!
但这个过程有几个问题要考虑。第一点,如果接收方有多个网卡,我怎么知道“hello”包是通过哪个网卡接收的呢?第二点,在接收方我可以用监听那个广播端口的socket来发送消息嘛?
对于第一点,也是苦恼了我很久的问题,最终找到了方法:getsockname,这个函数可以根据addr来得到ip地址,用C语言学习网络编程的都知道接收函数是有一个sockaddr_in结构体来接收发送方的ip和端口信息的,而这个函数就是根据这个结构体来解析的,但是这个函数有一个条件是一定要在连接的情况下才能获取本地ip地址,不过也对,连接了,网卡一定也就确定了。既然要连接那反正udp套接字也可以connect,我们多写一点就是了。
对于第二点,答案是不可以,因为我也尝试了这样的做法,在发送方接收到的ip消息会出现乱码的情况。所以在发送方和接收方都要多创建一个用于传送该消息的socket。总体来说就是,发送方和接收方都要有一个socket用来广播"hello"包和接收"hello"包,并且还都要有一个udp socket来发送udp消息和接收udp消息。
话不多说,上代码
//发送方--广播“hello”包然后接收接收方发送的ip消息
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <WinSock2.h>
#pragma comment (lib,"ws2_32.lib")#define BUF_SIZE 100
void error_handling(const char* message);int main(int argc,char* argv[])
{WSADATA wsadata;if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0)error_handling("wsastartup error!");if (argc != 2) {printf("usage: %s <port>\n", argv[0]);exit(1);}SOCKET send_sock,recv_sock;SOCKADDR_IN broad_adr;char send_msg[BUF_SIZE]="hello,world",rec_msg[BUF_SIZE];;int so_brd = 1;//创建send_sock并与广播地址进行关联send_sock = socket(PF_INET,SOCK_DGRAM,0);if (send_sock == INVALID_SOCKET)error_handling("send_sock error!");memset(&broad_adr,0,sizeof(broad_adr));broad_adr.sin_family = AF_INET;broad_adr.sin_addr.s_addr = htonl(INADDR_BROADCAST);broad_adr.sin_port = htons(atoi(argv[1]));//设置广播选项int getinfo = setsockopt(send_sock,SOL_SOCKET,SO_BROADCAST,(const char*)&so_brd,sizeof(so_brd));if (getinfo == SOCKET_ERROR) error_handling("setsockopt error!");printf("setsockopt has done\n");//创建recv_sock并与本地地址进行绑定recv_sock = socket(PF_INET, SOCK_DGRAM, 0);if (recv_sock == INVALID_SOCKET)error_handling("recv_sock error!");struct sockaddr_in myadr, youradr;memset(&myadr, 0, sizeof(myadr));myadr.sin_family = AF_INET;myadr.sin_addr.s_addr = htonl(INADDR_ANY);myadr.sin_port = htons(10244);if (bind(recv_sock, (struct sockaddr*)&myadr, sizeof(myadr)) == SOCKET_ERROR)error_handling("bind error!");else printf("bind has done\n");//发送helloworld消息int send_len;send_len = sendto(send_sock,send_msg,strlen(send_msg),0,(SOCKADDR*)&broad_adr,sizeof(broad_adr));if(send_len == -1)error_handling("sendto error!");else printf("sendto has done\n");closesocket(send_sock); //发送完后关闭发送的socket//接收来自receive.cpp运行端的ip消息并输出ipint yadr_sz = sizeof(youradr);int recv_len = recvfrom(recv_sock, rec_msg, BUF_SIZE, 0, (SOCKADDR*)&youradr, &yadr_sz);if (recv_len == -1)error_handling("recvfrom error!");else {printf("%s\n", rec_msg);}closesocket(recv_sock);WSACleanup();return 0;
} void error_handling(const char* message)
{printf("%s\n", message);exit(1);
}
//发送方接收到“hello”包后获取本机ip地址然后封装到udp数据报里发送
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <WinSock2.h>
#include <WS2tcpip.h>
#pragma comment (lib,"ws2_32.lib")
#define BUF_SIZE 100
void error_handling(const char* message);int main(int argc, char* argv[])
{WSADATA wsadata;if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0)error_handling("wsastartup error!");if (argc != 2) {printf("usage: %s <port>\n", argv[0]);exit(1);}char rec_msg[BUF_SIZE],send_msg[BUF_SIZE] = "the receiver ip is ";SOCKET send_sock,recv_sock;send_sock = socket(PF_INET, SOCK_DGRAM, 0);if (send_sock == INVALID_SOCKET)error_handling("send_sock error!");recv_sock = socket(PF_INET, SOCK_DGRAM, 0);if(recv_sock == INVALID_SOCKET)error_handling("recv_sock error!");SOCKADDR_IN adr,youradr;//set adrmemset(&adr, 0, sizeof(adr));adr.sin_family = AF_INET;adr.sin_addr.s_addr = htonl(INADDR_ANY);adr.sin_port = htons(atoi(argv[1]));//bind socket and adrif (bind(recv_sock,(SOCKADDR*)&adr,sizeof(adr)) == -1)error_handling("bind error!");else printf("bind has done\n");//receive messageint your_adr_sz = sizeof(youradr);int strlen = recvfrom(recv_sock, rec_msg, BUF_SIZE, 0, (SOCKADDR*)&youradr, &your_adr_sz);if (strlen == -1)error_handling("recvfrom error!");else {//输出接收到的消息和发送端的ip地址char* ip = inet_ntoa(youradr.sin_addr);printf("the message from sender: %s\n", rec_msg);printf("the sender ip is : %s\n", ip);//与发送端建立连接,通过getsockname得到自己的ip地址,将自己的ip地址发送给发送端//getsockname函数要在连接时才能得到本地ip地址,所以要先connect//另外要注意在发送端的接收socket的端口设定在10244,所以在这里也要改下youradr.sin_port = htons(10244);int con = connect(send_sock, (SOCKADDR*)&youradr, your_adr_sz);if (con == 0)printf("connect has done\n");else error_handling("connect error!");SOCKADDR_IN myaddr;int sz = sizeof(myaddr);int ret = getsockname(send_sock, (SOCKADDR*)&myaddr, &sz); //得到我自己的IP地址if (ret != 0)error_handling("getsockname error!");printf("my ip is %s", inet_ntoa(myaddr.sin_addr));char temp[BUF_SIZE];char *myip = inet_ntoa(myaddr.sin_addr);strcpy(temp, myip);strncat(send_msg, temp, ::strlen(temp)); //这里strlen前面加::是因为我前面有一个strlen变量重名了int sendmsg_sz = ::strlen(send_msg);send_msg[sendmsg_sz] = '\0';sendmsg_sz++;//printf("send_msg:%s\n", send_msg);int sendlen = send(send_sock,send_msg,sendmsg_sz,0);if (sendlen == -1)error_handling("sendto error!");else printf("send has done\n");}closesocket(send_sock);closesocket(recv_sock);WSACleanup();return 0;
}void error_handling(const char* message)
{printf("%s\n", message);exit(1);
}
以下是在虚拟机上调试的结果:
通过广播获取ip地址的实现相关推荐
- centos7修改ip地址自动获取_南京课工场IT培训:如何搭建DHCP服务器及自动获取IP地址及相关操作...
DHCP服务相关理论知识 DHCP服务分为以下三点, IP地址(例:192.168.1.0) 子网掩码(例:255.255.255.0) 网关 DHCP服务的好处: 减少管理员的工作量 避免输入错误的 ...
- kali linux查询自己的ip,Kali Linux常用服务配置教程获取IP地址
Kali Linux常用服务配置教程获取IP地址 下面以Kali Linux为例,演示获取IP地址的方法 (1)设置网络接口为自动获取IP地址.在Kali Linux的收藏夹中单击图标,将显示所有的程 ...
- 搭建局域网,通过DHCP实现电脑自动获取IP地址
完成这项实验需要在华为研发的ensp中进行 DHCP:动态主机配置协议 --同一分发管理ip地址 在一个广播域中,设置一台DHCP的服务器,之后需要ip地址的终端设备通过广播寻找到dhcp的服务器后 ...
- 计算机自动获取IP地址流程详解
计算机自动获取IP地址流程详解 你知道吗? 我们在日常生活中直接插上网线接口就可以直接上网,不需要拨号上网也不需要设置IP地址.那么我们在日常是怎么获得IP地址的呢? 这里就需要介绍一种服务是由Int ...
- DHCP自动获取ip地址
文章目录 前言 一:DHCP概述 1.1:DHCP产生的背景: 1.2:DHCP应用场景: 1.3:DHCP报文类型: 1.4:DHCP工作原理: 二:实验环境 2.1: 华为ensp软件 2.2: ...
- DHCP自动获取IP地址的过程(自动获取ip地址的过程)
我们电脑(或者W5500)在自动获取IP地址的过程(通过DHCP请求获取IP的过程),电脑是客户端,路由器是DHCP客户端. 1.DHCP的请求的总过程 1.1在 DHCP请求的过程中,包括 4 个主 ...
- DHCP客户端获取IP地址的过程
dhclient -r eth0 ##清除一下ip dhclient eth0 ##使用dhcp自动获取ip ip a ##查看ip 补充相关命令行知识 DHCP租约过程就是DHCP客户机动态获取IP ...
- 通过DHCP获取IP地址,使相关PC可以互相访问
HCIA中关于DHCP的常见问题 首先我们要了解何为DHCP DHCP服务 – 动态主机配置协议 统一分发管理ip地址: 在网络中部署一台DHCP服务器,之后终端设备通过广播来寻找DHCP服务器获取i ...
- CentOS 7如何设置Linux开机自动获取IP地址
centos7 minimal版默认安装好后没有获取ip地址,需要手动配置.方法如下: 1.输入"ip addr"并按回车键确定,发现无法获取IP(CentOS 7默认没有ifco ...
最新文章
- Android学习CursorWrapper与Decorator模式
- python【蓝桥杯vip练习题库】ALGO-77 斜率计算
- 分布式从mysql查数据_技术分享 | 从库数据的查找和参数 slave_rows_search_algorithms...
- Java代码实现负载均衡五种算法
- 质量属性效用树例子_数百个 HTML5 例子学习 HT 图形组件 – 拓扑图篇
- LeetCode 9. Palindrome Number
- python递归函数对照表_python-访问递归函数中附加到列表的值
- 雪花算法id长度_【Java】分布式自增ID算法雪花算法 (snowflake,Java版)
- 广义表取表头表尾_数据结构广义表的递归算法
- 获取文本上字符出现的次数,把数据写入文件
- 【软考软件评测师】2018综合知识历年真题
- Java 常用技术栈 相关概念总结, 更新中...
- Maven —— was cached in the local repository, resolution will not be reattempted until the update ...
- imazing是什么?iPhone苹果第三方iOS设备管理软件
- echarts 曲线面积对比图
- 浅谈网络中数字签名技术
- 中英对照泰戈尔《飞鸟集》(一)
- MAPI 、 IMAP4、 POP3、 SMTP 都是什么协议?
- 免费全功能响应式模板:黑暗元素
- codeforces Good Bye 2022
热门文章
- Unity_Shader高级篇_15_Unity Shader入门精要_消融效果
- L2接口提供的都是实时股票行情吗?
- Linux查询端口和进程相关命令
- [树状数组]数星星 Stars
- vue 项目打包通过命令修改 vue-router 模式,修改 API 接口前缀
- Mysql学习------MySQL运算符
- 王振辉博鳌谈本地生活服务升级,京东物流正式推出“闪电送”
- 2022-2027年中国丙肝药物行业市场调研及未来发展趋势预测报告
- GridView显示图片(图文)
- RuneWords-----神符之语