网络编程之UDP多点通讯
【1】网络属性
man getsockopt man 3 getsockopt 更新man手册 sudo apt-get install manpages-de manpages-de-dev manpages-dev glibc-doc manpages-posix-dev manpages-posix
功能:获取和设置网络属性; 头文件:#include <sys/types.h> /* See NOTES */#include <sys/socket.h> 原型:int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);int a = 1;setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &a, sizeof(a));参数:int sockfd:指定要设置/获取属性的套接字;int level:指定要控制套接字的层次;SOL_SOCKET 应用层,通用套接字选项; man 7 socketIPPROTO_TCP: TCP选项 man 7 tcpIPPROTO_UDP: UDP选项; man 7 udpIPPROTO_IP: IP选项; man 7 ipint optname:指定控制方式;以下以 SOL_SOCEKT为例:man 7 socketSO_REUSEADDR:允许端口快速重用SO_RCVBUF:接收缓冲区大小;SO_SNDBUF:发送缓冲区大小;SO_BROADCAST:广播;void *optval:根据optname的不同,数据类型不同;socklen_t* optlen:optval指向的变量的大小; 返回值:成功,返回0;失败,返回-1,更新errno;
【2】多点通讯
1. 单播
注意之间一对一的通信,交换机和路由器对数据只做转发不做复制;
每次只有两个实体相互通讯,发送端和接收端都是唯一确定的。
2. 广播
1)概念
主机之间一对多的通信方式,网络对其中每一台主机发出的信息都进行无条件复制并转发;
所有主机都可以接收到所有信息,无论你是否需要,由于其不用路径选择,所以其网络成本比较低;
禁止广播数据穿过路由器,防止广播数据造成大面积影响
只有UDP才能广播
广播的地址:主机号全是1
192.168.1.41那么他的广播地址192.168.1.255;
255.255.255.255 给所有网段中的所有主机发送广播,但是由于广播数据不能穿过路由器,所以实际上是给当前局域网下的主机发送;
2)广播的发送端流程(类似客户端)
创建报式套接字 (socket)
可选择绑定也可以不绑定地址信息结构体 (bind)
设置网络属性:允许广播,如果不设置,默认是不允许的(setsockopt)
填充广播的地址信息结构体:端口号 IP地址(广播IP 例如192.168.1.255 255.255.255.255)
发送数据 (sendto)
3)广播的接收端流程(类似服务器)
创建报式套接字 (socket)
必须绑定地址信息结构体:绑定广播IP地址(192.168.1.255 或者 0.0.0.0)和 端口号 (bind)
注意:绑定的端口号必须和发送端填充的端口号一致;
等待接收数据(recvfrom)
4)发送方代码
#include <stdio.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/ipc.h> #include <arpa/inet.h> #include <netinet/in.h> #include <string.h> #include <unistd.h> #define ERR_MSG(msg) do{\fprintf(stderr, "__%d__ :", __LINE__);\perror(msg);\ }while(0) #define PORT 2222 #define IP "192.168.1.255" //255.255.255.255 #define N 128 int main(int argc, const char *argv[]) {//创建报式套接字int sfd = socket(AF_INET, SOCK_DGRAM, 0);if(sfd < 0){ERR_MSG("socket");return -1;} //允许广播int broad = 1;if(setsockopt(sfd, SOL_SOCKET, SO_BROADCAST, &broad, sizeof(broad))<0){ERR_MSG("setsockopt");return -1;} //填充地址服务器信息结构体struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(PORT);sin.sin_addr.s_addr = inet_addr(IP); char buf[N] = "";while(1){bzero(buf, sizeof(buf)); printf("请输入>>>");fgets(buf, sizeof(buf), stdin);buf[strlen(buf)-1] = 0; //将数据发送到服务器if(sendto(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&sin, sizeof(sin))<0){ERR_MSG("sendto");return -1;}printf("发送成功\n");} close(sfd);return 0; }
5)接收方代码
#include <stdio.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/ipc.h> #include <arpa/inet.h> #include <netinet/in.h> #include <string.h> #include <unistd.h> #define ERR_MSG(msg) do{\fprintf(stderr, "__%d__ :", __LINE__);\perror(msg);\ }while(0) #define PORT 2222 #define IP "192.168.1.255" //0.0.0.0 #define N 128 int main(int argc, const char *argv[]) {//创建报式套接字int sfd = socket(AF_INET, SOCK_DGRAM, 0);if(sfd < 0){ERR_MSG("socket");return -1;} //允许端口快速重用int reuse = 1;if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))<0){ERR_MSG("setsockopt");return -1;} //填充地址信息结构体struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(PORT);sin.sin_addr.s_addr = inet_addr(IP); //绑定地址信息if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin))<0){ERR_MSG("bind");return -1;}printf("bind success\n"); char buf[N] = "";struct sockaddr_in cin;socklen_t addrlen = sizeof(cin);while(1){//接收bzero(buf, sizeof(buf));if(recvfrom(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&cin, &addrlen ) < 0){ERR_MSG("recvfrom");return -1;} printf("[%s:%d] %s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), buf);} close(sfd);return 0; }
3. 组播
1)概念
广播方式是发送给同一网段下的所有主机,过多的广播会占用大量网络带宽,会造成广播风暴,影响正常通讯;
主机之间一对一组的通讯模式,也就是只有加入了同一个组的主机可以接收到此组内的所有数据;
网络中的交换机和路由器只向需求者复制并转发数据;
组播IP地址: D类IP地址: 224.0.0.0~239.255.255.255
2)组播的发送端流程(类似客户端)
创建报式套接字 (socket)
可选择绑定也可以不绑定地址信息结构体 (bind)
填充接收方的IP地址及端口:IP地址:组播IP地址(224.0.0.0~239.255.255.255)
发送数据(sendto)
3)组播的接收端流程 (类似服务器)
创建报式套接字 (socket)
加入多播组 (setsockopt)
必须绑定地址信息结构体:IP地址:绑定组播IP地址(例如:224.1.2.3 或者 0.0.0.0)和端口 (bind)
注意:绑定的组播IP和端口号必须与发送方填充的一致;
等待接收数据(recvfrom)
4)如何加入多播组
功能:获取和设置网络属性; 头文件:#include <sys/types.h> /* See NOTES */#include <sys/socket.h> 原型:int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);参数:int sockfd:指定要设置属性的套接字;int level:指定要控制套接字的层次;IPPROTO_IP: IP选项; man 7 ipint optname:指定控制方式;IP_ADD_MEMBERSHIPvoid *optval:根据optname的不同,数据类型不同;struct ip_mreqn {struct in_addr imr_multiaddr; //组播Ip地址的网络字节序struct in_addr imr_address; //本机IP地址的网络字节序int imr_ifindex; //当前使用的网络设备索引号/*1.ifconfig 找到网卡名 例如:"ens33".ip ad 找到"ens33"对应的索引号,例如:22.通过函数的方式查找if_nametoindex(网卡的名字); 例如:if_nametoindex("ens33");3.填0,默认索引号*/}; socklen_t optlen:optval指向的变量的大小; 返回值:成功,返回0;失败,返回-1,更新errno;
5)发送端代码
#include <stdio.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/ipc.h> #include <arpa/inet.h> #include <netinet/in.h> #include <string.h> #include <unistd.h> #define ERR_MSG(msg) do{\fprintf(stderr, "__%d__ :", __LINE__);\perror(msg);\ }while(0) #define PORT 2222 #define IP "224.1.2.3" //224.0.0.0~239.255.255.255 #define N 128 int main(int argc, const char *argv[]) {//创建报式套接字int sfd = socket(AF_INET, SOCK_DGRAM, 0);if(sfd < 0){ERR_MSG("socket");return -1;} //填充地址接收方地址信息结构体struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(PORT);sin.sin_addr.s_addr = inet_addr(IP); char buf[N] = "";int i = 0;while(1){/*sprintf(buf, "hello %d", i);i++;*/bzero(buf, sizeof(buf)); printf("请输入>>>");fgets(buf, sizeof(buf), stdin);buf[strlen(buf)-1] = 0; //将数据发送到服务器if(sendto(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&sin, sizeof(sin))<0){ERR_MSG("sendto");return -1;}printf("发送成功\n");} close(sfd);return 0; }
6)接收端代码
#include <stdio.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/ipc.h> #include <arpa/inet.h> #include <netinet/in.h> #include <string.h> #include <unistd.h> #include <net/if.h> #define ERR_MSG(msg) do{\fprintf(stderr, "__%d__ :", __LINE__);\perror(msg);\ }while(0) #define PORT 2222 #define GROUP_IP "224.1.2.3" //224.0.0.0~239.255.255.255 与发送放一致 #define N 128 int main(int argc, const char *argv[]) {//创建报式套接字int sfd = socket(AF_INET, SOCK_DGRAM, 0);if(sfd < 0){ERR_MSG("socket");return -1;} //允许端口快速重用int reuse = 1;if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))<0){ERR_MSG("setsockopt");return -1;} //加入多播组struct ip_mreqn mq;mq.imr_multiaddr.s_addr = inet_addr(GROUP_IP); //组播Ip地址mq.imr_address.s_addr = inet_addr("192.168.1.12"); //本机IP地址mq.imr_ifindex = if_nametoindex("ens33"); //网络设备索引号 if(setsockopt(sfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mq, sizeof(mq)) < 0){ERR_MSG("setsockopt");return -1;} //填充地址信息结构体struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(PORT);sin.sin_addr.s_addr = inet_addr(GROUP_IP); //组播地址 //绑定地址信息if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin))<0){ERR_MSG("bind");return -1;}printf("bind success\n"); char buf[N] = "";struct sockaddr_in cin;socklen_t addrlen = sizeof(cin);while(1){//接收bzero(buf, sizeof(buf));if(recvfrom(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&cin, &addrlen ) < 0){ERR_MSG("recvfrom");return -1;} printf("[%s:%d] %s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), buf);} close(sfd);return 0; }
【3】项目:基于UDP的网络聊天室
1. 需求
项目需求:
如果有用户登录,其他用户可以收到这个人的登录信息
如果有人发送信息,其他用户可以收到这个人的群聊信息
如果有人下线,其他用户可以收到这个人的下线信息
服务器可以发送系统信息
写项目的方法:
画流程图
根据流程图写框架
将每个功能实现(一个一个实现,不要一起写)
2. 流程图
3.项目代码
GitHub - xuyongxiang/ChatRoom: 基于UDP的网络聊天室
网络编程之UDP多点通讯相关推荐
- Python中的网络编程之UDP
Python中的网络编程之UDP 文章目录 Python中的网络编程之UDP 一.Socket编程 `1.什么是客户端/服务器架构`? **`2.套接字:通信端点`** 3.套接字地址:主机-端口对 ...
- 萌新解--Java网络编程之UDP
Java网络编程之UDP UDP协议为无连接的通信协议,在传数据前发送端与接收端不会先建立连接,也就是你发我就收但不一定会收到哦,以我们自身为发送端,我们不会事先让接收方知道我要给接收方发数据啦.就像 ...
- 1.6 网络编程之 UDP通信
************************************************** * 本文由小鸟飞飞整理发表 <samboy@sohu.com> * * 首发网站:蓝丽 ...
- Java网络编程之UDP和TCP套接字
文章目录 一. 网络编程概述 二. UDP网络编程 1. UDP套接字 2. UDP客户端回显服务器程序 2.1 UDP回显服务器 2.2 UDP客户端 2.3 UDP实现查词典的服务器 三. TCP ...
- java网络编程udp_Java网络编程之UDP
UDP是User Datagram Protocol的简称,中文名是用户数据报协议,是OSI(Open System Interconnection,开放式系统互联)参考模型中一种无连接的传输层协议, ...
- java udp 同一个端口实现收发_Java网络编程之UDP协议
伙伴们注意了! 小编在这里给大家送上关注福利: 搜索微信公众号"速学Java"关注即可领取小编精心准备的资料一份! 今天我们来聊聊 网络编程这部分的内容 网络编程 1)计算机网络 ...
- Linux C高级编程——网络编程之UDP(4)
Linux网络编程--UDP 宗旨:技术的学习是有限的,分享的精神是无限的. 下面分析一帧基于UDP的TFTP协议帧. 以太网首部 0000: 00 05 5d 67 d0 b1 00 05 5d 6 ...
- python udp创建addr_一篇文章搞定Python 网络编程之UDP协议
基于UDP协议的socket PS:udp是无连接的,先启动那一端都不会报错 server端 import socket # 导入socket模块udp_sk = socket.socket(type ...
- C#网络编程之 UDP编程
C# 网络编程 UDP 转载于:https://www.cnblogs.com/miniwiki/archive/2009/07/24/1709833.html
最新文章
- python---简单数据库
- Kimera:一个基于度量语义的SLAM开源库
- Linux的ELF格式分析
- SAP Customer Data Cloud(Gigya)的用户搜索实现
- 认证授权方案之授权揭秘 (上篇)
- 实验2 java_《Java程序设计》实验2
- 他让全世界凶手睡不着觉,现实版福尔摩斯,退休了4次又被拽回来工作,无敌实在是太寂寞了~...
- Servlet读取文件的最好的方式
- Impala:大数据丛林中敏捷迅速的黑斑羚
- 大家不要催!雷军的螺丝刀已经准备好了...
- 雷赛控制卡系统集成源代码。整理归零,运行,暂停,停止。单轴调 试,位置移动,气缸操作,参数设置,IO监控,系统报警显示等等
- c语言 拟合指数函数的代码,如何找到拟合指数函数的x?
- Technorati.com 被劫持
- Stripe 自动分账
- 服务器站点地址是什么意思,云服务器地址是什么意思
- ***虚拟专用网技术
- 讲一点点自动驾驶技术(1)概论
- soso地图api接口poi检索示例----并在信息框显示经纬度
- 7-1 sdut-求一个3*3矩阵对角线元素之和7-2 求矩阵各行元素之和7-3 sdut- 对称矩阵的判定7-4 sdut- 杨辉三角7-5 sdut- 鞍点计算7-6 矩阵转置
- 一个BUG(缺陷)的生命周期
热门文章
- 中专计算机专业具体学习内容是什么?
- 【物联网】17.物联网传感器信号处理 - 信号放大电路
- 论文阅读笔记:Glyce: Glyph-vectors for Chinese Character Representations
- matlab 开环系统 求相位裕度,用MATLAB进行控制系统的..
- Spring拦截器HandlerInterceptor和HandlerInterceptorAdapter
- 【保研之路】北邮人工智能、天大计算机、中国科学技术大学
- QoS的流分类与标记
- Matlab 两种比较三个数的大小
- 瑞典军事研究:从认知心理学的视角探讨军事创新进程
- Java 100-002:Swing显示窗口,并在窗口中显示文字