引言

在进行网络程序的设计时,有时候我们不想要手动指定接收方的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地址的实现相关推荐

  1. centos7修改ip地址自动获取_南京课工场IT培训:如何搭建DHCP服务器及自动获取IP地址及相关操作...

    DHCP服务相关理论知识 DHCP服务分为以下三点, IP地址(例:192.168.1.0) 子网掩码(例:255.255.255.0) 网关 DHCP服务的好处: 减少管理员的工作量 避免输入错误的 ...

  2. kali linux查询自己的ip,Kali Linux常用服务配置教程获取IP地址

    Kali Linux常用服务配置教程获取IP地址 下面以Kali Linux为例,演示获取IP地址的方法 (1)设置网络接口为自动获取IP地址.在Kali Linux的收藏夹中单击图标,将显示所有的程 ...

  3. 搭建局域网,通过DHCP实现电脑自动获取IP地址

    完成这项实验需要在华为研发的ensp中进行 DHCP:动态主机配置协议  --同一分发管理ip地址 在一个广播域中,设置一台DHCP的服务器,之后需要ip地址的终端设备通过广播寻找到dhcp的服务器后 ...

  4. 计算机自动获取IP地址流程详解

    计算机自动获取IP地址流程详解 你知道吗? 我们在日常生活中直接插上网线接口就可以直接上网,不需要拨号上网也不需要设置IP地址.那么我们在日常是怎么获得IP地址的呢? 这里就需要介绍一种服务是由Int ...

  5. DHCP自动获取ip地址

    文章目录 前言 一:DHCP概述 1.1:DHCP产生的背景: 1.2:DHCP应用场景: 1.3:DHCP报文类型: 1.4:DHCP工作原理: 二:实验环境 2.1: 华为ensp软件 2.2: ...

  6. DHCP自动获取IP地址的过程(自动获取ip地址的过程)

    我们电脑(或者W5500)在自动获取IP地址的过程(通过DHCP请求获取IP的过程),电脑是客户端,路由器是DHCP客户端. 1.DHCP的请求的总过程 1.1在 DHCP请求的过程中,包括 4 个主 ...

  7. DHCP客户端获取IP地址的过程

    dhclient -r eth0 ##清除一下ip dhclient eth0 ##使用dhcp自动获取ip ip a ##查看ip 补充相关命令行知识 DHCP租约过程就是DHCP客户机动态获取IP ...

  8. 通过DHCP获取IP地址,使相关PC可以互相访问

    HCIA中关于DHCP的常见问题 首先我们要了解何为DHCP DHCP服务 – 动态主机配置协议 统一分发管理ip地址: 在网络中部署一台DHCP服务器,之后终端设备通过广播来寻找DHCP服务器获取i ...

  9. CentOS 7如何设置Linux开机自动获取IP地址

    centos7 minimal版默认安装好后没有获取ip地址,需要手动配置.方法如下: 1.输入"ip addr"并按回车键确定,发现无法获取IP(CentOS 7默认没有ifco ...

最新文章

  1. Android学习CursorWrapper与Decorator模式
  2. python【蓝桥杯vip练习题库】ALGO-77 斜率计算
  3. 分布式从mysql查数据_技术分享 | 从库数据的查找和参数 slave_rows_search_algorithms...
  4. Java代码实现负载均衡五种算法
  5. 质量属性效用树例子_数百个 HTML5 例子学习 HT 图形组件 – 拓扑图篇
  6. LeetCode 9. Palindrome Number
  7. python递归函数对照表_python-访问递归函数中附加到列表的值
  8. 雪花算法id长度_【Java】分布式自增ID算法雪花算法 (snowflake,Java版)
  9. 广义表取表头表尾_数据结构广义表的递归算法
  10. 获取文本上字符出现的次数,把数据写入文件
  11. 【软考软件评测师】2018综合知识历年真题
  12. Java 常用技术栈 相关概念总结, 更新中...
  13. Maven —— was cached in the local repository, resolution will not be reattempted until the update ...
  14. imazing是什么?iPhone苹果第三方iOS设备管理软件
  15. echarts 曲线面积对比图
  16. 浅谈网络中数字签名技术
  17. 中英对照泰戈尔《飞鸟集》(一)
  18. MAPI 、 IMAP4、 POP3、 SMTP 都是什么协议?
  19. 免费全功能响应式模板:黑暗元素
  20. codeforces Good Bye 2022

热门文章

  1. Unity_Shader高级篇_15_Unity Shader入门精要_消融效果
  2. L2接口提供的都是实时股票行情吗?
  3. Linux查询端口和进程相关命令
  4. [树状数组]数星星 Stars
  5. vue 项目打包通过命令修改 vue-router 模式,修改 API 接口前缀
  6. Mysql学习------MySQL运算符
  7. 王振辉博鳌谈本地生活服务升级,京东物流正式推出“闪电送”
  8. 2022-2027年中国丙肝药物行业市场调研及未来发展趋势预测报告
  9. GridView显示图片(图文)
  10. RuneWords-----神符之语