UDP广播实现多人聊天室

原理

        将UDP广播发送方与接收方进行融合,使的在一个ip端口上,既可以向这个广播上的所有人发送消息,也可以接收所有人的消息。最后屏蔽自己所发的每一条消息。

思路:

        需要创建出接收和发送的文件描述符,做好不同且合理的定义,利用select或者(poll)函数,实现收发。

        在处理自己所发消息会被自己所接收问题上,如果屏蔽发送与收到的相同消息,则如果其他人发送消息与自己一致,也会顺带屏蔽,如果屏蔽一次这样的消息,那么后续其他人发的消息虽然能收到,但也会收到来自自己紧接着发送的这样的消息。

        以下代码采用中间数组保留上一次收发的消息,利用flag记录消息的异同,避免了自己所发的消息被自己收到的尴尬情况。

#include <stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
int main(int argc, char *argv[])
{ 
    int sockfd,ret,sockfd1;
    char sendbuf[1024]={0},recvbuf[1024]={0},buf[1024]={0},sbuf[1024]={0};
    sockfd=socket(AF_INET,SOCK_DGRAM,0);        //创建网络套接字
    if(-1==sockfd)
    {
        perror("socket");
        exit(-1);
    }
    int on=1;
    ret = setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,&on,sizeof(on));
    struct sockaddr_in saddr;
    bzero(&saddr,sizeof(saddr));
    saddr.sin_family=AF_INET;
    saddr.sin_port=htons(8888);
    saddr.sin_addr.s_addr=inet_addr("192.168.2.255");//设置广播属性(发送)

    sockfd1=socket(AF_INET,SOCK_DGRAM,0);
    if(-1==sockfd1)
    {
        perror("socket");
        exit(-1);
    }
    struct sockaddr_in caddr;
    bzero(&caddr,sizeof(caddr));
    caddr.sin_family=AF_INET;
    caddr.sin_port=htons(8888);
    caddr.sin_addr.s_addr=inet_addr("192.168.2.255");
    socklen_t clen = sizeof(caddr);
    ret=bind(sockfd1,(struct sockaddr*)&caddr,clen);
    if(-1==ret)
    {
        perror("bind");
        close(sockfd1);
        exit(-1);
    }
//设置接收
    fd_set rfds,fds;
    FD_ZERO(&rfds);
    FD_SET(0,&rfds);
    FD_SET(sockfd,&rfds);
    FD_SET(sockfd1,&rfds);
    int nfds=sockfd1+1;
    int flag=0,flag1=0;
    sleep(1);
    printf("chatroom create sucess!\n");
    while(1)
    {
        fds=rfds;
        ret=select(nfds,&fds,NULL,NULL,NULL);
        if(ret<0)
        {
            perror("select");
            break;
        }                        //多路并用
        for(int i=0;i<nfds;i++)
        {
            if(FD_ISSET(i,&fds))
            {
                if(i==0||i==sockfd)
                {
                    bzero(sendbuf,1024);
                    scanf("%s",sendbuf);
                   if(strcmp(sendbuf,buf)==0)
                    {
                        flag++;
                    }
                   strcpy(buf,sendbuf);
                    ret=sendto(sockfd,sendbuf,1024,0,(struct sockaddr*)&saddr,sizeof(saddr));
                    if(ret<0)
                    {
                        perror("sendto");
                        return -1;
                    }
                    printf("send over\n");

                }
                if(i==sockfd1)
                {
                    bzero(recvbuf,1024);
                    ret=recvfrom(sockfd1,recvbuf,1024,0,(struct sockaddr*)&caddr,&clen);
                    if(ret<0)
                    {
                        perror("recvform");
                        close(sockfd);
                        exit(-1);
                    }
                   if(strcmp(recvbuf,sbuf)!=0)
                   {
                        flag1=0;
                   }    //收到的消息与上次收到的消息不一致flag1置0
                   strcpy(sbuf,recvbuf);
                    if(strcmp(sendbuf,recvbuf)==0&&flag1==0)
                    {   
                        flag1++;
                        continue;
                    }    
                    else if(flag!=0)
                    {
                        flag--;
                        continue;
                    }
                    else
                    {
                        printf("MSG: ");
                        printf("%s\n",recvbuf);
                        flag1=0;
                    }

                }
            }
        }
    }
    close(sockfd);
    return 0;

} 
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小珂打代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值