网络编程(三)—— UDP(单播、广播、组播)

这篇具有很好参考价值的文章主要介绍了网络编程(三)—— UDP(单播、广播、组播)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、单播

  1. UDP协议的特点:

    1. 无连接 、不保证传输可靠(可能重复到达、失序、丢失、无字节流控制(数据传输快的会淹没慢的))

    2. UDP传输
      udp单播和组播,嵌入式学习,网络编程,网络,udp,单片机

  2. UDP 服务端(接收端)的搭建流程
    udp单播和组播,嵌入式学习,网络编程,网络,udp,单片机

  3. UDP客户端(发送端)的搭建流程

udp单播和组播,嵌入式学习,网络编程,网络,udp,单片机

  1. 通信流程

udp单播和组播,嵌入式学习,网络编程,网络,udp,单片机

  1. sendto 和 recvfrom

    1. 这两个函数一般在使用UDP协议时使用

    2. sendto

         功能: sendto - send a message on a socket
         
         头文件:
                #include <sys/socket.h>
         函数原型:
                ssize_t sendto(int socket, const void *message, size_t length,
                       int flags, const struct sockaddr *dest_addr,
                       socklen_t dest_len);
         参数说明:
             	int socket: 通信套接字
             	const void *message: 要发送的数据(消息)
             	size_t length:发送的长度
                      int flags:发送的方式: 默认 0
                  const struct sockaddr *dest_addr: 要发送的目标地址:(指定对方的ip等)
                       socklen_t dest_len: 大小
                      
         返回值:
                成功: 返回成功的字节数
                失败: 返回-1并设置errno 
  1. recvfrom
      功能: recvfrom - receive a message from a socket
      
      头文件:
             #include <sys/socket.h>
      函数原型:
             ssize_t recvfrom(int socket, void *restrict buffer, size_t length,
                    int flags, struct sockaddr *restrict address,
                    socklen_t *restrict address_len);
      参数说明:
          	int socket: 通信套接字
          	void *restrict buffer: 接收保存数据(消息)
          	size_t length:发送的长度
                   int flags:发送的方式: 默认 0
               struct sockaddr *restrict address:对方的ip
                    socklen_t *restrict address_len: 地址长度
                   
      返回值:
             成功: 返回成功的字节数
             失败: 返回-1并设置errno 
      
  1. 单播就是普通版的UDP 服务器和客户端

代码示例

服务器端

/*===============================================
*   文件名称:UdpServer.c
*   创 建 者:   
*   创建日期:
*   描    述:
================================================*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>


int main(int argc, char *argv[])
{ 
    /*
    if( argc < 3 )
    {
        puts("arg err");
        return -1;
    }
    */
    //创建套接字
    int sockfd = socket(AF_INET ,SOCK_DGRAM,0);
    if( -1 == sockfd )
    {
        perror("socket fail");
        return -1;
    }

    //准备需要发送数据的服务器ip和端口

    struct sockaddr_in  ser_addr = {
    .sin_family  =  AF_INET ,
    .sin_port    =  htons(8888),
    .sin_addr.s_addr = inet_addr("0")
    };

    //绑定
    int ret = bind(sockfd,(struct sockaddr*)&ser_addr,sizeof(ser_addr));
    if( -1 == ret )
    {
        perror("bind ");
        return -1 ;
    }
    //发送数据
    char buf[BUFSIZ] = {0};
    while(1)
    {
        memset(buf,0,BUFSIZ);
        ret = recvfrom(sockfd,buf,BUFSIZ,0,NULL,NULL);
        if( -1 == ret)
        {
            perror("recv");
            return -1;
        }
        // sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*)&ser_addr,sizeof(ser_addr));
        puts(buf);
    }

    close(sockfd);
    return 0;
} 

客户端

/*===============================================
 *   文件名称:UdpClient.c
 *   创 建 者: 
 *   创建日期:2023年08月25日
 *   描    述:
 ================================================*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>


int main(int argc, char *argv[])
{ 
   
    //创建套接字
    int sockfd = socket(AF_INET ,SOCK_DGRAM,0);
    if( -1 == sockfd )
    {
        perror("socket fail");
        return -1;
    }

    //准备需要发送数据的服务器ip和端口

    struct sockaddr_in  ser_addr = {
        .sin_family  =  AF_INET ,
        //.sin_port    =  htonl(atoi(argv[2])),
        .sin_port    =  htons(8888),
        //.sin_addr.s_addr = inet_addr(argv[1])
        .sin_addr.s_addr = inet_addr("192.168.18.196")
    };

    //发送数据
    char buf[BUFSIZ] = {0};
    char rbuf[BUFSIZ] = {0};
    while(1)
    {
        fgets(buf,sizeof(buf),stdin);
        int ret = sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*)&ser_addr,sizeof(ser_addr));

        if( -1 == ret )
        {
            perror("sendto fail");
            return -1;
        }

        //recvfrom(sockfd,rbuf,BUFSIZ,0,NULL,NULL);
        //
        puts(buf);
    }

    close(sockfd);
    return 0;
} 

二、广播

定义:给同一网段的所有主机 发送 数据

如何实现:需要给发送端开启 广播权限,并且 发送的目标地址是 广播地址


代码示例
服务器端

/*===============================================
*   文件名称:UdpServer.c
*   创 建 者:    
*   创建日期:
*   描    述:
================================================*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>


int main(int argc, char *argv[])
{ 
 
    //创建套接字
    int sockfd = socket(AF_INET ,SOCK_DGRAM,0);
    if( -1 == sockfd )
    {
        perror("socket fail");
        return -1;
    }

    //准备需要发送数据的服务器ip和端口

    struct sockaddr_in  ser_addr = {
    .sin_family  =  AF_INET ,
    .sin_port    =  htons(6666),
    .sin_addr.s_addr = inet_addr("0")
    };

    //绑定
    int ret = bind(sockfd,(struct sockaddr*)&ser_addr,sizeof(ser_addr));
    if( -1 == ret )
    {
        perror("bind ");
        return -1 ;
    }
    //发送数据
    char buf[BUFSIZ] = {0};
    while(1)
    {
        memset(buf,0,BUFSIZ);
        ret = recvfrom(sockfd,buf,BUFSIZ,0,NULL,NULL);
        if( -1 == ret)
        {
            perror("recv");
            return -1;
        }
        // sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*)&ser_addr,sizeof(ser_addr));
        puts(buf);
    }

    close(sockfd);
    return 0;
} 

客户端
/*===============================================
 *   文件名称:UdpClient.c
 *   创 建 者:   
 *   创建日期:
 *   描    述:
 ================================================*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>


int main(int argc, char *argv[])
{ 
   
    //创建套接字
    int sockfd = socket(AF_INET ,SOCK_DGRAM,0);
    if( -1 == sockfd )
    {
        perror("socket fail");
        return -1;
    }

    //准备需要发送数据的服务器ip和端口

    struct sockaddr_in  ser_addr = {
        .sin_family  =  AF_INET ,
        //.sin_port    =  htonl(atoi(argv[2])),
        .sin_port    =  htons(6666),
        //.sin_addr.s_addr = inet_addr(argv[1])
        .sin_addr.s_addr = inet_addr("192.168.18.255") //广播地址 
    };

    //开播广播权限
    int opt = 1 ;
   // setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt));
   // 
    setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt));

    //发送数据
    char buf[BUFSIZ] = {0};
    char rbuf[BUFSIZ] = {0};
    while(1)
    {
        fgets(buf,sizeof(buf),stdin);
        int ret = sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*)&ser_addr,sizeof(ser_addr));

        if( -1 == ret )
        {
            perror("sendto fail");
            return -1;
        }

    }

    close(sockfd);
    return 0;
} 

三、组播(多播)

  1. 有选择的接收 客户端的数据
  2. 是在接收端加入多播组
组播在发送者和每一接收者之间实现点对多点网络连接。如果一台发送者同时给多个接收者传输相同的数据,也只需
复制一份相同的数据包。它提高了数据传送效率,减少了骨干网络出现拥塞的可能性。组播解决了单播和广播方式
效率低的问题。当网络中的某些用户需求特定信息时,组播源(即组播信息发送者)仅发送一次信息,组播路由器借助
组播路由协议为组播数据包建立树型路由,被传递的信息在尽可能远的分叉路口才开始复制和分发。

代码示例(服务器端)文章来源地址https://www.toymoban.com/news/detail-756167.html

/*===============================================
*   文件名称:UdpServer.c
*   创 建 者:
*   创建日期:
*   描    述:
================================================*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>


int main(int argc, char *argv[])
{ 
    /*
    if( argc < 3 )
    {
        puts("arg err");
        return -1;
    }
    */
    //创建套接字
    int sockfd = socket(AF_INET ,SOCK_DGRAM,0);
    if( -1 == sockfd )
    {
        perror("socket fail");
        return -1;
    }

    //准备需要发送数据的服务器ip和端口

    struct sockaddr_in  ser_addr = {
    .sin_family  =  AF_INET ,
    .sin_port    =  htons(8888),
    .sin_addr.s_addr = inet_addr("0")
    };
        

    //组播
    struct ip_mreqn group = {
        .imr_multiaddr.s_addr = inet_addr("224.224.224.224"),//组播地址:224.0.0.1——239
        .imr_address.s_addr =htonl(INADDR_ANY)//绑定本机ip

    };

    //设置组播权限
    
    if( -1 == setsockopt(sockfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&group,sizeof(group)))
    {
        perror("setsocket");
        return -1;
    }




    //绑定
    int ret = bind(sockfd,(struct sockaddr*)&ser_addr,sizeof(ser_addr));
    if( -1 == ret )
    {
        perror("bind ");
        return -1 ;
    }
    //发送数据
    char buf[BUFSIZ] = {0};
    while(1)
    {
        memset(buf,0,BUFSIZ);
        ret = recvfrom(sockfd,buf,BUFSIZ,0,NULL,NULL);
        if( -1 == ret)
        {
            perror("recv");
            return -1;
        }
        // sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*)&ser_addr,sizeof(ser_addr));
        puts(buf);
    }

    close(sockfd);
    return 0;
} 

客户端
#include <stdio.h>
#include <string.h>
 #include <sys/types.h>          /* See NOTES */  //man  socket
 #include <sys/socket.h>
 #include <sys/socket.h>    //  man 7 ip
 #include <netinet/in.h>
 #include <netinet/ip.h> /* superset of previous */
#include <sys/socket.h>  //man 3 inet_addr  
#include <netinet/in.h>
#include <arpa/inet.h>  //man 2 read 
#include <unistd.h>

#define SIZE 1024
#define SERV_IP "0"
#define SERV_PORT 6666

//UDP 客户端
int main(int argc,const char *argv[])
{
    int connfd; 
    int ret; 
    //1. socket
    connfd = socket(AF_INET, SOCK_DGRAM, 0); // udp:SOCK_DGRAM 
    if(-1 == connfd)
    {
        perror("socket");
        return -1;
    }
    //2. 填充ip 要连接的目标 ip 和端口
    struct sockaddr_in dest_addr = {
      .sin_family     = AF_INET, 
        .sin_port     = htons(SERV_PORT), 
        .sin_addr.s_addr = inet_addr("127.0.0.1")
    };
    //4.通信
    char buf[SIZE] = {0}; 
    while(1)
    {
        fgets(buf,  sizeof(buf)-1, stdin); 
        if(0 == strncmp(buf, "quit",4))
        {
            break; 
        }
        sendto(connfd, buf, sizeof(buf), 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr)); 
    }
    //关闭套接字
    
    close(connfd);
    return 0;

}

到了这里,关于网络编程(三)—— UDP(单播、广播、组播)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Linux网络编程系列之UDP广播

            1、 Linux网络编程系列之网络编程基础         2、 Linux网络编程系列之TCP协议编程         3、 Linux网络编程系列之UDP协议编程         4、 Linux网络编程系列之UDP广播         5、 Linux网络编程系列之UDP组播         6、 Linux网络编程系列之服务器编程——阻塞IO模型

    2024年02月04日
    浏览(30)
  • Qt网络编程 (udp广播和接收例)

    使用两个项目 1 sender 用来广播\\\"hello world\\\"; 2 receiver 用来接收广播信息 1 创建Qdialog类 2 在sender.pro 中添加 QT +=network 一行代码 3 在sender.h 中声明类 class QUdpSocket; 在声明一个私有对象 QUdpSocket *sender; 4 在ui界面拖入一个按钮 用来触发广播信息 其槽函数如下 在sender.cpp 构造函数中添

    2024年02月11日
    浏览(33)
  • QT网络编程之实现UDP广播发送和接收

    一.UDP广播介绍 UDP广播地址固定IP地址为:XXX.XXX.XXX.255。 如果向全网段发送广播消息,那么广播地址为:255.255.255.255; 如果向单个网段发送广播消息,例如你的IP是192.168.31.104,那么广播地址为192.168.31.255。 广播消息接收方需要绑定0.0.0.0地址并监听指定端口即可收到广播的群

    2024年03月25日
    浏览(51)
  • udp多点通信-广播-组播

    单播 每次只有两个实体相互通信,发送端和接收端都是唯一确定的。 主机之间的一对多的通信 所有的主机都可以接收到广播消息(不管你是否需要) 广播禁止穿过路由器(只能做局域网通信) 只有UDP可以广播 广播地址 有效网络号+全是1的主机号 192.168.50.123 -----》 192.168.5

    2024年02月05日
    浏览(31)
  • 网络编程——UDP编程

    在C语言中进行UDP编程的一般步骤如下: (1) 包含头文件 : 在代码中包含必要的头文件,以便使用UDP编程所需的函数和数据类型。通常情况下,你需要包含 sys/socket.h、netinet/in.h 和 arpa/inet.h。 (2) 创建套接字 : 使用 socket() 函数创建一个套接字,该套接字将用于网络通信

    2024年02月05日
    浏览(35)
  • infinispan~组播和广播

    Infinispan 是一个基于分布式系统的内存数据存储和缓存平台,它的集群实现原理涉及到节点的发现和通信。在 Infinispan 中,集群是由多个节点组成的,每个节点都存储着数据的一部分,并且通过通信来保持数据的一致性和可用性。 Infinispan 集群的实现原理主要包括以下几个关

    2024年02月12日
    浏览(31)
  • Linux网络编程——UDP编程

    1、UDP通信协议,服务器端和客户端无需建立连接,只需要知道对方套接字的地址信息就可以发送数据 2、UDP通信流程图: 功能:创建套接字并返回套接字描述符 功能:将套接字与IP地址和端口号绑定 功能:发送数据 功能:接收数据 功能:关闭套接字 1、代码功能:两个进程

    2023年04月19日
    浏览(38)
  • 网络编程 p5 UDP编程

    基本介绍 类DatagramSocket和DatagramPacket实现了基于UDP协议网络程序。 UDP数据报通过数据报套接字DatagramSocket发送和接收,系统不保证UDP数据报一定能够安全送到目的地,也不能确定什么时候可以抵达。 DatagramPacket对象封装了UDP数据报, 在数据报中包含了发送端的IP地址和端口号

    2024年02月16日
    浏览(32)
  • 单播,广播,组播

    只有一个源点网络和一个终点网络。源点网络和终点网络的关系是一对一的。数据报途径的每一个路由器都要将这个分组仅从一个接口转发出去。 单播是主机间一对一的通讯模式,网络中的设备根据网络报文中包含的目的地址选择传输路径,将单播报文传送到指定的目的地,

    2023年04月08日
    浏览(32)
  • 网络原理(三)—— UDP网络编程

    概念 :Socket 套接字,是由操作系统提供用于网络通信的技术,是基于TCP/IP协议的网络通信的基本操作单元。基于Socket 套借字的网络程序开发就是网络编程。 通俗点来说,咱们程序员在写网络程序,其实主要编写的是应用层代码!(因为底层的哪些你动不了,也改变不了)也

    2024年01月19日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包