c语言实现udp广播和组播

目录

1、UDP广播通信

2、UDP组播通信

1、UDP广播通信

单播:数据包发送方式只有一个接受方

广播:同时发给局域网中的所有主机

只有用户数据报套接字(使用UDP协议)才能广播

以192.168.63.0网段为例:..***.255 代表该网段的广播地址。发送给该地址的数据包被所有主机接收

实现广播的过程(UDP协议)

 广播发送端: ----> 添加广播属性

1、建立套接字

2、设置该套接字允许进行广播(将广播属性添加进去),填充服务端的结构体

3、将数据发送到广播地址中(sendto(buf,192.168.x.x))

4、关闭

接收端(服务器): ----> 绑定所有主机(INADDR_ANY)

1、建立套接字

2、填充服务端的结构体,绑定广播地址和端口号(struct sockaddr_in serveraddr,serveraddr.sin_addr.s_addr = htonl(INADDR_ANY)))(需要设置端口复用) 3、创建结构体存放客户端IP和端口,接收数据

4、关闭

//2、将广播属性添加到套接字中 int on = 1; setsockopt(socketfd,SOL_SOCKET,SO_BROADCAST,&on,sizeof(on)); ownaddr.sin_addr.s_addr = htonl(INADDR_ANY); //INADDR_ANY代表本机所有地址 常用方法

 广播的测试代码如下:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#define GUANG_IP "192.168.5.255"    //---> 你所在局域网的广播地址
#define GUANG_PORT 60000

//udp广播server.c
int main(int argc,char** argv)
{
    //如果手动输入IP和地址
    // if(argc != 3)
    // {
    //     perror("./a.out IP PORT");
    //     return -1;
    // }

    int ret = 0;
    char buf[1024] = { 0 };

    //1、创建一个套接字文件描述符
    int socketfd = socket(AF_INET,SOCK_DGRAM,0);
    if(socketfd == -1)
    {
        perror("socket fail");
        return -1;
    }

    //设置端口复用
    int optval = 1;
    setsockopt(socketfd,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval));

    //2、绑定广播IP和端口号
    struct sockaddr_in ownaddr;
    ownaddr.sin_family = AF_INET;
    //ownaddr.sin_port = htons(atoi(argv[2]));               //传参方式
    ownaddr.sin_port = htons(GUANG_PORT);                    //宏定义方式
    ownaddr.sin_addr.s_addr = htonl(INADDR_ANY);             //INADDR_ANY代表本机所有地址 常用方法
    ret = bind(socketfd,(struct sockaddr*)&ownaddr,sizeof(struct sockaddr_in));
    if(ret == -1)
    {
        perror("bind fail");
        return -1;
    }
    printf("绑定本机成功[%s][%d]\n",GUANG_IP,GUANG_PORT);

    //定义接收结构体,获取IP和端口
    struct sockaddr_in recv_addr;
    int len = sizeof(struct sockaddr_in);
    char *ip =NULL;
    int port = 0;

    //3、接收数据
    while(1)
    {
        //清空缓冲区
        bzero(buf,sizeof(buf));

        //接收数据
        ret = recvfrom(socketfd,buf,sizeof(buf),0,(struct sockaddr*)&recv_addr,&len);

        //解析发送端的ip和地址
        ip = inet_ntoa(recv_addr.sin_addr);
        port = ntohs(recv_addr.sin_port);

        printf("[%s][%d] 接收数据 buf:%s ret:%d\n",ip,port,buf,ret);

        if(strcmp(buf,"exit") == 0)
        {
            break;
        }

    }

    //4、关闭套接字
    close(socketfd);

    return 0;
}

//udp广播client.c
int main(int argc,char** argv)
{
    //如果手动输入IP和地址
    // if(argc != 3)
    // {
    //     perror("./a.out IP PORT");
    //     return -1;
    // }

    int ret = 0;
    char buf[1024] = { 0 };

    //1、创建一个套接字文件描述符
    int socketfd = socket(AF_INET,SOCK_DGRAM,0);
    if(socketfd == -1)
    {
        perror("socket fail");
        return -1;
    }

    //2、将广播属性添加到套接字中
    int on = 1;
    setsockopt(socketfd,SOL_SOCKET,SO_BROADCAST,&on,sizeof(on));

    //指定接收方
    struct sockaddr_in send_addr;
    send_addr.sin_family = AF_INET;
    send_addr.sin_port = htons(GUANG_PORT);
    send_addr.sin_addr.s_addr = inet_addr(GUANG_IP);
    printf("绑定本机成功[%s][%d]\n",GUANG_IP,GUANG_PORT);

    //3、发送数据
    while(1)
    {
        //清空缓冲区
        bzero(buf,sizeof(buf));

        scanf("%s",buf);

        ret = sendto(socketfd,buf,strlen(buf),0,(struct sockaddr*)&send_addr,sizeof(struct sockaddr_in));

        printf("发送数据 ret=%d\n",ret);

        if(strcmp(buf,"exit") == 0)
        {
            break;
        }

    }

    //4、关闭套接字
    close(socketfd);

    return 0;
}

2、UDP组播通信

组播是介于单播与广播之间,在一个局域网内,将某些主机添加到组中,并设置一个组地址.我们 只需要将数据发送到组播地址即可,加入到该组的所有主机都能接收到数据

组播特点

1)需要给组播设置IP地址,该IP必须是D类地址

2)只有UDP才能设置组播

3、IP地址分类 IP地址 = 网络号 + 主机号

网络号:指的是不同的网络

主机号:指的是同一个网段下用来识别不同的主机。

那也就是说,主机号所占的位数越多,在该网段下的主机 数越多

A类地址 :保留给政府机构使用

A类IP地址就由1字节的网络地址和3字节主机地址组成,网络地址的最高位必须 是“0”

A类地址范围 1.0.0.1 - 126.255.255.254

B类地址 :分配给中等规模的公司

B类IP地址就由2字节的网络地址和2字节主机地址组成,网络地址的最高位必须 是“10”

B类地址范围 128.0.0.1 - 191.255.255.254

C类地址 :分配给任何需要的人

C类IP地址就由3字节的网络地址和1字节主机地址组成,网络地址的最高位必须 是“110” 13 C类地址范围 192.0.0.1 - 223.255.255.254 //192.168.14.2

D类地址 :用于组播

D类地址范围 224.0.0.1 - 239.255.255.254 //224.0.0.10

E类地址 :用于实验

E类地址范围 240.0.0.1 - 255.255.255.254

特殊地址:

每一个字节都为0的地址(“0.0.0.0”)对应于当前主机;

INADDR_ANY -->代表当前主机所有的地址

127.0.0.1 回环地址 --》在当前主机内部自动形成闭环的网络 --》主要用于主机内部不同的应用程序通信

如果你已经确定当前客户端 和 服务器 都是在同一台主机上运行,那么可以使用这个地址

组播通信的过程

 UDP组播发送端

1、建立套接字()

2、发送数据,往群聊(组播地址)中发送数据

3、关闭

UDP组播接收端

1、建立套接字

2.定义组播结构体

3、设置组播ip(初始化 组播结构体)

4.加入组播属性(也就是设置这个套接字 可以接收组播信息)

5、绑定IP地址和端口号

6、进群,加入群聊,将当前的IP地址设置到组播地址中

7、创建结构体存放客户端IP和端口,接收数据

8、关闭

 UDP组播的测试代码如下:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define GROUP_IP    "224.0.0.10"  //组播地址224开头
#define GROUP_PORT  60000

#define MY_IP   "192.168.5.184"

//udp组播server.c
int main()
{
    int ret = 0;

    //1.建立套接字
    int socket_fd = socket(AF_INET,SOCK_DGRAM,0);
    if(socket_fd < 0)
    {
        perror("socket fail");
        return -1;
    }

    //2.定义组播结构体
    struct ip_mreq vmreq;

    //3、设置组播ip(初始化 组播结构体)
    inet_pton(AF_INET,"224.0.0.10",&vmreq.imr_multiaddr); // 组播地址
    inet_pton(AF_INET,"192.168.5.184",&vmreq.imr_interface); // 需要添加到组的ip

    //4.加入组播属性(也就是设置这个套接字 可以接收组播信息)
    setsockopt(socket_fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&vmreq,sizeof(vmreq));

    //5.绑定本机地址
    struct sockaddr_in my_addr;
    my_addr.sin_family = AF_INET;//地址族
    my_addr.sin_port = htons(GROUP_PORT);//端口号
    my_addr.sin_addr.s_addr = htonl(INADDR_ANY); //INADDR_ANY代表本机所有地址 常用方法 注意
    ret = bind(socket_fd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr_in));
    if(ret < 0)
    {
        perror("bind fail");
        return -1;
    }
    printf("绑定本机成功[%s][%d]\n",GROUP_IP,GROUP_PORT);

    //6.接收数据
    char buf[1024] = {0};
    struct sockaddr_in recv_addr;
    socklen_t addrlen = sizeof(struct sockaddr_in);
    char *ip = NULL;
    int port = 0;
    while(1)
    {
        bzero(buf,sizeof(buf));

        ret = recvfrom(socket_fd,buf,sizeof(buf),0,(struct sockaddr *)&recv_addr,&addrlen);
        
        ip = inet_ntoa(recv_addr.sin_addr);
        port = ntohs(recv_addr.sin_port);

        printf("[%s][%d]buf:%s ret:%d\n",ip,port,buf,ret);
    }

    //关闭套接字
    close(socket_fd);

    return 0;
}

//udp组播client.c
int main()
{
    int ret = 0;
    char buf[1024] = { 0 };

    //1、建立套接字
    int socket_fd = socket(AF_INET,SOCK_DGRAM,0);
    if(socket_fd < 0)
    {
        perror("socket fail");
        return -1;
    }

    //给组播地址发送数据
    struct sockaddr_in send_addr;
    send_addr.sin_family = AF_INET;//地址族
    send_addr.sin_port = htons(GROUP_PORT);//端口号
    send_addr.sin_addr.s_addr = inet_addr(GROUP_IP); //ip地址

    while(1)
    {
        //清空缓存区
        bzero(buf,sizeof(buf));
        
        scanf("%s",buf);

        ret = sendto(socket_fd,buf,strlen(buf),0,(struct sockaddr *)&send_addr,sizeof(struct sockaddr_in ));
        
        printf("发送数据 ret:%d\n",ret);

    }

    //关闭套接字
    close(socket_fd);

    return 0;
}

  • 9
    点赞
  • 80
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
下面是c语言实现UDP和TCP的网络聊天室的大致步骤: ## UDP 1. 创建UDP Socket,设置套接字选项以支持广播和多播。 2. 绑定Socket到本地IP地址和端口号。 3. 加入多播组或者广播地址。 4. 接收其他客户端发送的消息并显示在聊天窗口中。 5. 用户在聊天窗口中输入消息后,将消息通过UDP Socket广播给其他客户端。 6. 关闭Socket。 在实现过程中,需要注意以下几点: - 接收数据时需要注意消息的可靠性,可以通过检测消息的长度和校验和来判断消息是否有误,避免出现丢失、重复或乱序的情况。 - 发送数据时需要注意UDP的数据报大小限制,避免发送过大的数据报导致消息丢失或分片重组错误。 - 需要注意多播组和广播地址的使用,避免消息发送到错误的地址。 ## TCP 1. 创建TCP Socket,建立连接并进行数据传输。 2. 接收其他客户端发送的消息并显示在聊天窗口中。 3. 用户在聊天窗口中输入消息后,将消息通过TCP Socket发送给其他客户端。 4. 关闭Socket。 在实现过程中,需要注意以下几点: - 建立连接时需要进行三次握手,建立连接后才能进行数据传输。 - 需要注意TCP的流量控制和拥塞控制,避免数据传输过程中出现拥塞和丢失。 - 需要注意TCP协议的半关闭和全关闭操作,避免出现资源泄露和连接状态不一致的情况。 以上是c语言实现UDP和TCP的网络聊天室的大致步骤,具体实现细节需要根据实际情况进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值