大学网站首页设计,国内产品设计网站,公司做公司网站,网站排名优化怎么做Linux网络编程系列 #xff08;够吃#xff0c;管饱#xff09; 1、Linux网络编程系列之网络编程基础 2、Linux网络编程系列之TCP协议编程 3、Linux网络编程系列之UDP协议编程 4、Linux网络编程系列之UDP广播 5、Linux网络编程系列之UDP组播 6、Linux网络编程系列之服务器编…Linux网络编程系列 够吃管饱 1、Linux网络编程系列之网络编程基础 2、Linux网络编程系列之TCP协议编程 3、Linux网络编程系列之UDP协议编程 4、Linux网络编程系列之UDP广播 5、Linux网络编程系列之UDP组播 6、Linux网络编程系列之服务器编程——阻塞IO模型 7、Linux网络编程系列之服务器编程——非阻塞IO模型 8、Linux网络编程系列之服务器编程——多路复用模型 9、Linux网络编程系列之服务器编程——信号驱动模型
一、什么是UDP广播 UDP广播是一种网络通信的方式在广域网或局域网中UDP广播可以向多个目标主机发送数据包使得网络中的所有设备都能接收到广播消息。一定是采用UDP协议。
二、特性 1、面向无连接UDP广播不需要建立连接可以直接发送数据包到目标设备。 2、广播特性UDP广播可以向一个网络中的所有设备发送数据包。 3、不可靠性UDP广播发送的数据包无法保证传输的可靠性可能会发生数据丢失、错误等情况。 4、速度快、开销小UDP广播不需要建立连接因此传输速度快开销小适用于实时流媒体传输等应用场景。 5、 安全性较低UDP广播发送的数据包可以被网络中的其他设备接收可能会存在数据泄露的风险。 6、适用于广播通信场景UDP广播适用于需要向网络中所有设备发送数据的场景比如寻找可用设备、传输实时视频或音频数据等。
三、使用场景 UDP广播主要用于数据的实时传输和设备的发现常见的应用场景包括 1、视频和音频的实时传输UDP广播可以使得多个设备同时接收到同一流的数据实现实时的视频会议和音频播放等功能。 2、网络打印机的自动发现通过UDP广播打印机可以向网络中广播自己的存在从而被所有的设备发现和使用。 3、多人游戏的联机UDP广播可以将游戏数据同时发送给所有玩家的设备实现多人游戏的联机功能。 4、网络摄像头的实时监控通过UDP广播摄像头可以将实时的视频流发送给所有监控软件使得监控人员能够同时查看视频。
四、UDP广播通信流程 1、发送方不一定是服务器或者客户端 1、建立套接字。使用socket() 2、设置套接字属性为广播。使用setsockopt() 3、绑定自己的IP地址和端口号。使用bind()可以省略 4、发送数据并指定接收方为广播地址。使用sendto() 5、关闭套接字 2、接收方不一定是服务器或者客户端 1、建立套接字。使用socket() 2、设置端口复用。使用setsockopt()可选推荐 3、绑定IP地址为广播地址和端口号。使用bind()不可以省略 4、接收数据。使用recvfrom() 5、关闭套接字
五、相关函数API 1、建立套接字 // 建立套接字
int socket(int domain, int type, int protocol);// 接口说明返回值成功返回一个套接字文件描述符失败返回-1参数domain用来指定使用何种地址类型有很多具体看别的资源1PF_INET 或者 AF_INET 使用IPV4网络协议2其他很多的看别的资源参数type通信状态类型选择有很多具体看别的资源1SOCK_STREAM 提供双向连续且可信赖的数据流即TCP2SOCK_DGRAM 使用不连续不可信赖的数据包连接即UDP参数protocol用来指定socket所使用的传输协议编号通常不用管一般设为0 2、设置端口状态 // 设置端口的状态
int setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen);// 接口说明返回值成功返回0失败返回-1参数sockfd待设置的套接字参数level 待设置的网络层一般设成为SOL_SOCKET以存取socket层参数optname待设置的选项有很多种具体看别的资源这里讲常用的1、SO_REUSEADDR 允许在bind()过程中本地地址可复用即端口复用2、SO_BROADCAST 使用广播的方式发送通常用于UDP广播3、SO_SNDBUF 设置发送的暂存区大小4、SO_RCVBUF 设置接收的暂存区大小参数optval待设置的值参数optlen参数optval的大小即sizeof(optval) 3、绑定IP地址和端口号 // 绑定自己的IP地址和端口号int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);// 接口说明返回值参数sockfd待绑定的套接字参数addrlen参数addr的大小即sizeof(addr)参数addrIP地址和端口的结构体通用的结构体根据sockfd的类型有不同的定义当sockfd的domain参数指定为IPV4时结构体定义为struct sockaddr_in{unsigned short int sin_family; // 需与sockfd的domain参数一致uint16_t sin_port; // 端口号struct in_addr sin_addr; // IP地址 unsigned char sin_zero[8]; // 保留的未使用};struct in_addr{uin32_t s_addr;}
// 注意网络通信时采用大端字节序所以端口号和IP地址需要调用专门的函数转换成网络字节序 4、字节序转换接口 // 第一组接口
// 主机转网络IP地址输入主机IP地址
uint32_t htonl(uint32_t hostlong);// 主机转网络端口输入主机端口号
uint16_t htons(uint16_t hostshort); // 常用// 网络转主机IP输入网络IP地址
uint32_t ntohl(uint32_t netlong);// 网络转主机端口输入网络端口
uint16_t ntohs(uint16_t netshort);// 第二组接口只能用于IPV4转换IP地址
// 主机转网络
int inet_aton(const char *cp, struct in_addr *inp);// 主机转网络
in_addr_t inet_addr(const char *cp); // 常用// 网络转主机
int_addr_t inet_network(const char *cp);// 网络转主机
char *inet_ntoa(struct in_addr in); // 常用5、发送数据 // UDP协议发送数据
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);// 接口说明返回值成功返回成功发送的字节数失败返回-1参数sockfd发送者的套接字参数buf发送的数据缓冲区参数len发送的长度参数flags一般设置为0还有其他数值具体查询别的资源参数dest_addr接收者的网络地址参数addrlen接收者的网络地址大小即sizeof(dest_addr) 6、接收数据 // UDP协议接收数据
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);// 接口说明返回值成功返回成功接收的字节数失败返回-1参数sockfd接收者的套接字参数buf接收数据缓的冲区参数len接收的最大长度参数flags一般设置为0还有其他数值具体查询别的资源参数src_addr发送者的网络地址可以设置为NULL参数addrlen 发送者的网络地址大小即sizeof(src_addr) 7、关闭套接字 // 关闭套接字
int close(int fd);// 接口说明返回值成功返回0失败返回-1参数fd套接字文件描述符 六、案例 实现UDP广播的演示 发送方BroadcastSend.c // UDP广播发送方的案例#include stdio.h
#include unistd.h
#include string.h
#include sys/types.h
#include sys/socket.h
#include netinet/in.h
#include netinet/ip.h
#include arpa/inet.h#define SEND_IP 192.168.64.128 // 记得改为自己IP
#define SEND_PORT 10000 // 不能超过65535也不要低于1000防止端口误用int main(int argc, char *argv[])
{// 1、建立套接字使用IPV4网络地址UDP协议int sockfd socket(AF_INET, SOCK_DGRAM, 0);if(sockfd -1){perror(socket fail);return -1;}// 2、设置套接字为广播属性int optval 1; // 这里设置套接字为广播属性所以随便写一个值int ret setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, optval, sizeof(optval));if(ret -1){perror(setsockopt fail);close(sockfd);return -1;}// 3、绑定自己的IP地址和端口号可以省略struct sockaddr_in send_addr {0};socklen_t addr_len sizeof(struct sockaddr);send_addr.sin_family AF_INET; // 指定协议为IPV4地址协议send_addr.sin_port htons(SEND_PORT); // 端口号send_addr.sin_addr.s_addr inet_addr(SEND_IP); // IP地址ret bind(sockfd, (struct sockaddr*)send_addr, addr_len);if(ret -1){perror(bind fail);close(sockfd);return -1;}// 4、发送数据uint16_t port 0; // 端口号char ip[20] {0}; // IP地址struct sockaddr_in recv_addr {0};char msg[128] {0}; // 数据缓冲区// 注意输入广播地址格式为*.*.*.255printf(please input receiver IP and port\n);scanf(%s %hd, ip, port);printf(IP %s, port %hd\n, ip, port);recv_addr.sin_family AF_INET; // 指定用IPV4地址recv_addr.sin_port htons(port); // 接收者的端口号recv_addr.sin_addr.s_addr inet_addr(ip); // 接收者的IP地址while(getchar() ! \n); // 清空多余的换行符while(1){printf(please input data:\n);fgets(msg, sizeof(msg)/sizeof(msg[0]), stdin);// 发送数据注意要填写接收者的地址ret sendto(sockfd, msg, strlen(msg), 0, (struct sockaddr*)recv_addr, addr_len);if(ret 0){printf(success: send %d bytes\n, ret);}}// 5、关闭套接字close(sockfd);return 0;
} 接收方BroadcastRecv.c // UDP广播接收方的案例#include stdio.h
#include unistd.h
#include string.h
#include sys/types.h
#include sys/socket.h
#include netinet/in.h
#include netinet/ip.h
#include arpa/inet.h#define RECV_IP 192.168.64.255 // 记得改为广播地址
#define RECV_PORT 20000 // 不能超过65535也不要低于1000防止端口误用int main(int argc, char *argv[])
{// 1、建立套接字使用IPV4网络地址UDP协议int sockfd socket(AF_INET, SOCK_DGRAM, 0);if(sockfd -1){perror(socket fail);return -1;}// 2、设置端口复用推荐int optval 1; // 这里设置为端口复用所以随便写一个值int ret setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, optval, sizeof(optval));if(ret -1){perror(setsockopt fail);close(sockfd);return -1;}// 3、绑定自己的IP地址和端口号不可以省略struct sockaddr_in recv_addr {0};socklen_t addr_len sizeof(struct sockaddr);recv_addr.sin_family AF_INET; // 指定协议为IPV4地址协议recv_addr.sin_port htons(RECV_PORT); // 端口号// recv_addr.sin_addr.s_addr inet_addr(RECV_IP); // IP地址. 写下面的更好recv_addr.sin_addr.s_addr htonl(INADDR_ANY); // 本机内所有的IP地址ret bind(sockfd, (struct sockaddr*)recv_addr, addr_len);if(ret -1){perror(bind fail);close(sockfd);return -1;}// 4、接收数据uint16_t port 0; // 端口号char ip[20] {0}; // IP地址struct sockaddr_in send_addr {0};char msg[128] {0}; // 数据缓冲区while(1){// 接收数据注意使用发送者的地址来接收ret recvfrom(sockfd, msg, sizeof(msg)/sizeof(msg[0]), 0, (struct sockaddr*)send_addr, addr_len);if(ret 0){memset(ip, 0, sizeof(ip)); // 先清空IPstrcpy(ip, inet_ntoa(send_addr.sin_addr)); // 网络IP转主机IPport ntohs(send_addr.sin_port); // 网络端口号转主机端口号printf([%s:%d] send data: %s\n, ip, port, msg);memset(msg, 0, sizeof(msg)); // 清空数据区}}// 5、关闭套接字close(sockfd);return 0;
} 通信演示 注第一幅图由于只有一台电脑不太好演示广播效果第二幅图用了一台电脑和一个开发板。
七、总结 UDP广播一定是采用UDP协议的通信流程跟UDP协议的通信流程差不多就是要注意设置发送方套接字属性为广播然后设置接收方的IP地址为广播地址UDP广播主要用于数据的实时传输和设备的发现。