Step by step to create a chat program 2- epoll use to create simple chat room

 

 As shown, the video is viewed, the final job, in addition to unused select client implemented, other requirements are simple implementation.

The server code is as follows:

#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 ]; 
}; 

// set keepalive parameter keepalive_time keep alive, keepalive_intvl keep-alive interval, keepalive_probes number of keepalive probes. 
int set_keepalive ( int sockfd, int keepalive_time, int keepalive_intvl, int keepalive_probes) 
{ 
    int the optval; 
    the socklen_t optlen = the sizeof (the optval); 

    the optval = . 1 ;
     IF (- . 1 == the setsockopt (sockfd, SOL_SOCKET, the SO_KEEPALIVE, & the optval, optlen) ) 
    { 
        perror ( "setsockopt failture.\n");
        return -1;
    }

    optval=keepalive_probes;
    if(-1==setsockopt(sockfd,SOL_TCP,TCP_KEEPCNT, &optval,optlen))
    {
        perror("setsockopt failture.\n");
        return -1;
    }

    optval=keepalive_intvl;
    if(-1==setsockopt(sockfd,SOL_TCP,TCP_KEEPINTVL, &optval,optlen))
    {
        perror("setsockopt failture.\n");
        return -1;
    }

    optval=keepalive_time;
    if(-1==setsockopt(sockfd,SOL_TCP,TCP_KEEPIDLE, &optval, optlen))
    {
        perror("setsockopt failture\n");
        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\n");
        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 ++ ; 
        } 
        the else 
        { 
            strcpy (Users [I ++ ] .password, buf); 
            COUNT ++ ; 
        } 
    } 

    fclose (FD); 
} 

int main ( int argc , char * the argv []) 
{ 

    // read the user name and password set 
    struct user_password users [ 100 ]; 
    set_user_password (users); 
    for ( int I = 0 ; I < 2 ; I ++ ) 
    {
        printf("user: %s,\t password: %s\n",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\n");
        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\n");
        close(sd);
        return -1;
    }

    err=listen(sd,MAX_LISTEN);
    if(err==-1)
    {
        perror("listen failed\n");
        close(sd);
        return -1;
    }

    int epfd=epoll_create(EPOLL_SIZE);
    if(epfd<0)
    {
        perror("epoll create failed\n");
        return -1;
    }
    printf("epoll created, epollfd=%d\n",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\n");
        return -1;
    }

    while(1)
    {
        int epoll_events_count=epoll_wait(epfd,events,EPOLL_SIZE,-1);
        if(epoll_events_count<0)
        {
            perror("epoll wait failed\n");
            break;
        }

        printf("epoll_events_count= %d\n",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.\n");
                        continue;
                    }

                    printf("USER %d online\n",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\n");
                        return -1;
                    }
                }
                else
                {
                    memset(buf,0,100);
                    strcpy(buf,"login failed\n");
                    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\n");
                    return -1;
                }
                else if(bytes==0)
                {
                    err=epoll_ctl(epfd,EPOLL_CTL_DEL,sockfd,events);
                    if(err==-1)
                    {
                        perror("epoll del failed\n");
                        return -1;
                    }
                    printf("USER %d offline\n",sockfd);
                    close(sockfd);
                }
                else
                {
                    printf("recv message from cliend %d, buf: %s\n",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\n");
                        }
                    }
                    else if(strcmp(recv_message.buf,"quit")==0)//用户输入quit,客户端推出。
                    {
                        printf("USER %d offline\n",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\n");
                            continue;
                        }
                        close(fd);

                        printf("exec cmd: %s\n",cmd);

                        system(cmd);
                        memset(cmd,0,100);

                        //将结果回送客户端
                        fd=fopen("./test.txt","r");
                        if(fd==NULL)
                        {
                            perror("open file failed\n");
                            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;
}

The client code or previous versions, achieved without the use of 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: \n");
        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\n");
        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\n");
        close(sd);
        return -1;
    }

    pid_t pid=fork();
    if(pid==0)
    {
        while(1)
        {
            //读服务器发来的消息
            //printf("read message: \n");
            char revBuf[100];
            recv(sd,revBuf,100,0);
            //read(sd,revBuf,100);
            if(strcmp(revBuf,"quit")==0)
            {
                return 0;
            }
            printf("recevice from server: %s\n",revBuf);
        }
    }
    int flag=0;
    while(1)
    {
        printf("input message: \n");
        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\n");
            }
            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\n");
            }
            //write(sd,&send_message,sizeof(send_message));

        //}
        if(strcmp(send_message.buf,"quit")==0)
        {
            printf("USER offline\n");
            close(sd);
            return 0;
        }
        send_message.target_id=-1;
        memset(send_message.buf,0,sizeof(send_message.buf));
        sleep(3);
    }

    close(sd);
    return 0;
}

 

Guess you like

Origin www.cnblogs.com/JsonZhangAA/p/11965404.html