• 一步一步创建聊天程序2-利用epoll来创建简单的聊天室


     如图,这个是看视频时,最后的作业,除了客户端未使用select实现外,其它的要求都有简单实现。

    服务端代码如下:

    #include <stdio.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <errno.h>
    #include <sys/epoll.h>
    #include <netinet/in.h>
    #include <unistd.h>
    #include<netinet/tcp.h>
    
    #define MAX_LISTEN 10
    #define EPOLL_SIZE 100
    
    struct message
    {
        int target_id;
        char buf[100];
    };
    
    struct user_password
    {
        char username[100];
        char password[100];
    };
    
    //设置保活参数 keepalive_time保活时间,keepalive_intvl保活间隔,keepalive_probes保活探测数。
    int set_keepalive(int sockfd,int keepalive_time, int keepalive_intvl, int keepalive_probes)
    {
        int optval;
        socklen_t optlen= sizeof(optval);
    
        optval=1;
        if(-1==setsockopt(sockfd,SOL_SOCKET, SO_KEEPALIVE, &optval, optlen))
        {
            perror("setsockopt failture.
    ");
            return -1;
        }
    
        optval=keepalive_probes;
        if(-1==setsockopt(sockfd,SOL_TCP,TCP_KEEPCNT, &optval,optlen))
        {
            perror("setsockopt failture.
    ");
            return -1;
        }
    
        optval=keepalive_intvl;
        if(-1==setsockopt(sockfd,SOL_TCP,TCP_KEEPINTVL, &optval,optlen))
        {
            perror("setsockopt failture.
    ");
            return -1;
        }
    
        optval=keepalive_time;
        if(-1==setsockopt(sockfd,SOL_TCP,TCP_KEEPIDLE, &optval, optlen))
        {
            perror("setsockopt failture
    ");
            return -1;
        }
        return 0;
    }
    
    void set_user_password(struct user_password users[100])
    {
        int fd=fopen("./password.txt","r");
        if(fd==NULL)
        {
            perror("open password failed
    ");
            return;
        }
    
        char buf[100];
        int count=0;
        int i=0;
        while(feof(fd)==0)
        {
            fscanf(fd,"%s",buf);
            if(count%2==0)
            {
                strcpy(users[i].username,buf);
                count++;
            }
            else
            {
                strcpy(users[i++].password,buf);
                count++;
            }
        }
    
        fclose(fd);
    }
    
    int main(int argc,char * argv[])
    {
    
        //读取设定的用户名和密码
        struct user_password users[100];
        set_user_password(users);
        for(int i=0;i<2;i++)
        {
            printf("user: %s,	 password: %s
    ",users[i].username,users[i].password);
        }
    
    
        struct sockaddr_in server_ip,customer_ip;
        int err,sd;
    
        sd=socket(AF_INET,SOCK_STREAM,0);
        if(sd==-1)
        {
            perror("socket failed
    ");
            close(sd);
            return -1;
        }
    
        server_ip.sin_family=AF_INET;
        server_ip.sin_port=htons(5678);
        server_ip.sin_addr.s_addr=htonl(INADDR_ANY);
        memset(server_ip.sin_zero,0,8);
    
        err=bind(sd,(struct sockaddr *)(&server_ip),sizeof(struct sockaddr));
        if(err==-1)
        {
            perror("bind failed
    ");
            close(sd);
            return -1;
        }
    
        err=listen(sd,MAX_LISTEN);
        if(err==-1)
        {
            perror("listen failed
    ");
            close(sd);
            return -1;
        }
    
        int epfd=epoll_create(EPOLL_SIZE);
        if(epfd<0)
        {
            perror("epoll create failed
    ");
            return -1;
        }
        printf("epoll created, epollfd=%d
    ",epfd);
    
        struct  epoll_event events[EPOLL_SIZE];
        struct  epoll_event  event;
        event.data.fd=sd;
        event.events=EPOLLIN;
        err=epoll_ctl(epfd,EPOLL_CTL_ADD,sd,&event);
        if(err==-1)
        {
            perror("epoll add failed
    ");
            return -1;
        }
    
        while(1)
        {
            int epoll_events_count=epoll_wait(epfd,events,EPOLL_SIZE,-1);
            if(epoll_events_count<0)
            {
                perror("epoll wait failed
    ");
                break;
            }
    
            printf("epoll_events_count= %d
    ",epoll_events_count);
    
            for(int i=0;i<epoll_events_count;i++)
            {
                int sockfd=events[i].data.fd;
                if(sockfd==sd)
                {
                    int length=sizeof(struct sockaddr);
                    int client_fd=accept(sockfd,(struct sockaddr *)(&customer_ip),&length);
    
                    //用户名和密码检验
                    int flag=0;
                    char buf[100]="please input username and password ";
                    struct user_password login_user;
                    
                    send(client_fd,buf,100,0);
                    recv(client_fd,&login_user,sizeof(struct user_password),0);
                    memset(buf,0,100);
                    for(int i=0;i<100;i++)
                    {
                        if((strcmp(users[i].username,login_user.username)==0)&&(strcmp(users[i].password,login_user.password)==0))
                        {
                            flag=1;
                            break;
                        }
                    }
    
                    if(flag)
                    {
                        err=set_keepalive(sockfd,120,20,3);
                        if(err!=0)
                        {
                            perror("set keep alive failed.
    ");
                            continue;
                        }
    
                        printf("USER %d online
    ",client_fd);
                        event.data.fd=client_fd;
                        event.events=EPOLLIN;
                        err=epoll_ctl(epfd,EPOLL_CTL_ADD,client_fd,&event);
                        if(err==-1)
                        {
                            perror("epoll add failed
    ");
                            return -1;
                        }
                    }
                    else
                    {
                        memset(buf,0,100);
                        strcpy(buf,"login failed
    ");
                        send(client_fd,buf,100,0);
                    }
                    
                }
                else
                {
                    struct message recv_message;
                    int bytes=recv(sockfd,&recv_message,sizeof(struct message),0);
                    if(bytes<0)
                    {
                        perror("recv failed
    ");
                        return -1;
                    }
                    else if(bytes==0)
                    {
                        err=epoll_ctl(epfd,EPOLL_CTL_DEL,sockfd,events);
                        if(err==-1)
                        {
                            perror("epoll del failed
    ");
                            return -1;
                        }
                        printf("USER %d offline
    ",sockfd);
                        close(sockfd);
                    }
                    else
                    {
                        printf("recv message from cliend %d, buf: %s
    ",sockfd,recv_message.buf);
                        if(recv_message.target_id!=-1)//请求向客户端发送信息
                        {
                            err=send(recv_message.target_id,recv_message.buf,100,0);
                            if(err==-1)
                            {
                                perror("send failed
    ");
                            }
                        }
                        else if(strcmp(recv_message.buf,"quit")==0)//用户输入quit,客户端推出。
                        {
                            printf("USER %d offline
    ",sockfd);
                            send(sockfd,recv_message.buf,100,0);
                            close(sockfd);
                        }
                        else
                        {
                            char cmd[100];
                            strcat(cmd,recv_message.buf);
                            strcat(cmd," >> test.txt");
    
                            int fd=fopen("./test.txt","w");
                            if(fd==NULL)
                            {
                                perror("clear file failed
    ");
                                continue;
                            }
                            close(fd);
    
                            printf("exec cmd: %s
    ",cmd);
    
                            system(cmd);
                            memset(cmd,0,100);
    
                            //将结果回送客户端
                            fd=fopen("./test.txt","r");
                            if(fd==NULL)
                            {
                                perror("open file failed
    ");
                                continue;
                            }
                            char buf[100];
                            while(feof(fd)==0)
                            {
                                int fread_ret=fread(buf,sizeof(char),sizeof(buf),fd);
                                send(sockfd,buf,100,0);
                                memset(buf,0,128);
                            }
                            fclose(fd);
                        } 
                    }
                }
            }
        }
        return 0;
    }

    客户端代码还是之前的版本,没有使用select实现:

    #include <stdio.h>
    #include <pthread.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    
    struct message
    {
        int target_id;
        char buf[100];
    };
    
    struct user_password
    {
        char username[100];
        char password[100];
    };
    
    int sd;
    struct message send_message;
    
    void * read_message(void * argv)
    {
        while(1)
        {
            //读服务器发来的消息
            char revBuf[100];
            read(sd,revBuf,100);
            printf("recevice from server: %s",revBuf);
        }
    }
    
    void * write_message(void * argv)
    {
        while(1)
        {
            printf("input message: 
    ");
            memset(send_message.buf,0,128);
            send_message.target_id=-1;
            scanf("%d %s",&send_message.target_id,send_message.buf);
    
            write(sd,&send_message,sizeof(send_message));
            sleep(3);
        }
    }
    
    int main()
    {
        struct sockaddr_in server_ip,customer_ip;
        int err;
    
        sd=socket(AF_INET,SOCK_STREAM,0);
        if(sd==-1)
        {
            printf("socket failed
    ");
            close(sd);
            return -1;
        }
    
        //server_ip初始化
        server_ip.sin_family=AF_INET;
        server_ip.sin_port=htons(5678);
        server_ip.sin_addr.s_addr=htonl(INADDR_ANY);
        //err=inet_aton("115.157.201.179",&server_ip.sin_addr.s_addr);
        memset(server_ip.sin_zero,0,8);
    
        err=connect(sd,(struct sockaddr *)(&server_ip),sizeof(server_ip));
        if(err==-1)
        {
            printf("connect failed
    ");
            close(sd);
            return -1;
        }
    
        pid_t pid=fork();
        if(pid==0)
        {
            while(1)
            {
                //读服务器发来的消息
                //printf("read message: 
    ");
                char revBuf[100];
                recv(sd,revBuf,100,0);
                //read(sd,revBuf,100);
                if(strcmp(revBuf,"quit")==0)
                {
                    return 0;
                }
                printf("recevice from server: %s
    ",revBuf);
            }
        }
        int flag=0;
        while(1)
        {
            printf("input message: 
    ");
            if(flag++==0)
            {
                struct user_password login_user;
                scanf("%s %s",login_user.username,login_user.password);
                err=send(sd,&login_user,sizeof(struct user_password),0);
                if(err==-1)
                {
                    printf("send failed
    ");
                }
                continue;
            }
            memset(send_message.buf,0,128);
            send_message.target_id=-1;
            scanf("%d %s",&send_message.target_id,send_message.buf);
    
            //if(send_message.target_id!=-1&&(strcmp(send_message.buf,"")!=0))
            //{
                //err=send(sd,send_message.buf,100,0);
                err=send(sd,&send_message,sizeof(send_message),0);
                if(err==-1)
                {
                    printf("send failed
    ");
                }
                //write(sd,&send_message,sizeof(send_message));
    
            //}
            if(strcmp(send_message.buf,"quit")==0)
            {
                printf("USER offline
    ");
                close(sd);
                return 0;
            }
            send_message.target_id=-1;
            memset(send_message.buf,0,sizeof(send_message.buf));
            sleep(3);
        }
    
        close(sd);
        return 0;
    }
  • 相关阅读:
    oracle 数据库安全审计
    oracle 共享服务器监控
    oralce MTS
    配置一个Oracle共享服务器进程环境需要哪两项参数
    python3 小技巧(2)
    python3 操作注册表
    PYC文件简介
    常见HTTP状态(304,200等)
    用Python模拟浏览器操作
    python3下的IE自动化模块PAMIE
  • 原文地址:https://www.cnblogs.com/JsonZhangAA/p/11965404.html
Copyright © 2020-2023  润新知